如何在feeas.js中加载数据库表中的初始数据

问题描述 投票:0回答:1

这是我几个月来一直在思考的一个问题:

我正在寻找一种优雅、一致的方式来初始化表,第一次创建表时,使用feathin foams-knex

我正在使用feathers.js(5.0.5)+feathers-knex(8.0.1)+knex(2.4.2) 请注意,我已经用羽毛版本 4 解决了我的问题

我有一个由提供的生成器生成的服务:

...
const { Rootdir } = require('./rootdir.class');
const createModel = require('../../models/rootdir.model');
const hooks = require('./rootdir.hooks');

module.exports = function (app) {
  const options = {
    // id: 'id', // Optional
    Model: createModel(app),
    paginate: app.get('paginate')
  };
  app.use('/rootdir', new Rootdir(options, app));
  const service = app.service('rootdir');
  service.hooks(hooks);
}

rootdir.model.js 看起来像:

module.exports = function (app) {
  const db = app.get('knexClient');
  const tableName = 'rootdir';
  db.schema.hasTable(tableName).then(exists => {
    if (!exists) {
      db.schema.createTable(tableName, table => {
        table.string('id').primary();
        table.string('dir');
      })
        .then(() => {
          debug(`Created ${tableName} table`)
          app.emit(`table.${tableName}.created`)
        })
        .catch(e => console.error(`Error creating ${tableName} table`, e));
    }
    // At this point the table is not yet created!
    
  });

  return db;
};

rootdir.class.js 中没有什么特别的 - 只是生成器发出的标准内容:

const { Service } = require('feathers-knex');

exports.Rootdir = class Rootdir extends Service {
  constructor(options) {
    super({
      ...options,
      name: 'rootdir'
    });
  }
};

我需要初始化 - 即预加载一些数据 - 第一次创建表“rootdir”时。 这必须在创建服务之后但在处理第一个请求之前发生。 因此,当它遇到我的“初始化”代码时,需要完全解决承诺 db.schema.hasTable(db.schema.createTable(...)) 。

我发现解决这个问题的唯一方法是:

  • 创建表时发出事件“table.${tableName}.created”
  • 然后在我的主代码中的某个地方执行以下操作:
app.on('table.rootdir.created' , async () => {
  await populateRootdirTable()
})

但是,我觉得应该有一种方法可以拦截以下时刻:

  • 服务被实例化(app.hook['setup'])
  • 并且创建表(如果不存在)

我尝试过的:

我希望 createModel 可以返回一个承诺,然后该承诺将在服务中的“某个地方”得到解决。但不,服务需要“初始化的 knex 对象”作为“模型”属性。 因此,如果我尝试传递一个承诺而不是对 knex 的引用,代码就会失败。

我尝试将初始化代码放入应用程序设置挂钩中:

app.hooks({
  setup: [
    async function setupHook(context,next) {
      debug("setup hook called (before)");
      await next();
      const rootdirService = context.app.service('rootdir');
      const ret = await rootdirService.find({
        query: {
          $limit: 0
        }
      });
      console.log("ret:",ret);  
    }
  ],
  teardown: []
}
)

但是当代码到达钩子时,即使服务存在,表还没有创建 (只是为了正确性:它在您第二次启动应用程序时确实存在,因为那时该表已经创建;但第一次失败)

我应该把这个“初始化”代码放在哪里?我应该如何触发它? 或者说,我的想法完全错误吗?

javascript knex.js feathersjs
1个回答
0
投票

由于您使用的是 SQL,表创建和数据初始化是通过 迁移文件 完成的。在普通的 Feathers 5 应用程序中,您可以使用以下命令运行迁移:

npm run migrate
指南中

显示了如何创建迁移的示例。 创建表后,在迁移中您还可以通过导入来使用

app

对象:

import type { Knex } from 'knex'
import { app } from '../src/app'

export async function up(knex: Knex): Promise<void> {
  // create tables or make changes
  app.service('users').create(/* create admin user here */)
}

© www.soinside.com 2019 - 2024. All rights reserved.