Node.js 如何等待自动迁移启动脚本完成后再启动另一个脚本?

Node.js 如何等待自动迁移启动脚本完成后再启动另一个脚本?,node.js,loopbackjs,Node.js,Loopbackjs,我正在使用引导脚本创建一些模型和关系。例如,我可能有: +-------+ +----------+ | Order | --belongsTo--> | Customer | +-------+ +----------+ 我想创建:1个客户,以及属于该客户的1个订单 我知道loopback boot在中执行server/boot中的脚本,因此我有以下引导脚本: // 0-create-customer.js module.ex

我正在使用引导脚本创建一些模型和关系。例如,我可能有:

+-------+                +----------+
| Order | --belongsTo--> | Customer |
+-------+                +----------+
我想创建:1个
客户
,以及属于该
客户的1个
订单

我知道loopback boot在中执行
server/boot
中的脚本,因此我有以下引导脚本:

// 0-create-customer.js
module.exports = function(app) {
    app.dataSources.mongoDs.autoupdate('Customer', function(err) {
        if (err) throw err;
        var obj = {name: 'Bob'};
        app.models.Customer.findOrCreate({where: obj}, obj
        , function(err, customer) {
            if (err) throw err;
        });
    });
};
对于
订单
,我首先找到
客户
,并使用
Customer.id
创建订单:

// 1-create-order.js
module.exports = function(app) {
    app.dataSources.mongoDs.autoupdate('Order', function(err) {
        if (err) throw err;
        app.models.Customer.findOne({where: {name: 'Bob'}}
        , function(err, customer) {
            if (err) throw err;
            var obj = {customerId: customer.id, amount: 42};
            app.models.Order.findOrCreate({where: obj}, obj
            , function(err, order) {
                if (err) throw err;
            });
        });
    });
};
问题是,启动脚本似乎不会等到创建模型后才退出,因此有时我会在第二个脚本中遇到以下错误:

TypeError: Cannot read property 'id' of null
关于这一行:

            var obj = {customerId: customer.id, amount: 42};
                                   ^
我不希望在创建
订单之前添加一个小的等待时间,因为这看起来很脆弱,并且不能保证父模型的存在,尤其是在数据源速度较慢的情况下

我也不希望将所有这些代码合并到一个文件中,因为我真正的项目有很多模型,这将导致一个巨大的无法维护的文件


在启动子模型之前,是否有一种等待父模型自动迁移完成的好方法?

您可以使用额外的回调参数创建异步启动脚本,并在脚本准备就绪时调用它

例如:

module.exports = function (app, cb) {
  var db = app.dataSources.db;

  // update all database models
  db.autoupdate(function (err) {
    if (err) throw err;
    cb();
  });
};

您可以使用额外的回调参数创建异步启动脚本,并在脚本准备就绪时调用它

例如:

module.exports = function (app, cb) {
  var db = app.dataSources.db;

  // update all database models
  db.autoupdate(function (err) {
    if (err) throw err;
    cb();
  });
};
一种方法是直到在数据源中找到客户为止

因此,
Order
创建脚本可能如下所示:

// 1-create-order.js
module.exports = function(app) {
    app.dataSources.mongoDs.autoupdate('Order', function(err) {
        if (err) throw err;
        var customerId = null;
        function addOrder(customerName, obj) {
            if (customerId === null) {
                app.models.Customer.findOne(
                    {where: {name: customerName}}, function(err, customer) {
                    if (err) throw err;
                    if (customer !== null) {
                        customerId = customer.id;
                    }
                });
                setTimeout(addOrder, 1000, customerName, obj);
                return;
            }

            obj.customerId = customerId;
            app.models.Order.findOrCreate({where: obj}, obj
            , function(err, order) {
                if (err) throw err;
            });
        }
        addOrder('Bob', {amount: 42});
    });
}
因此,函数
addOrder
将使用
setTimeout
不断调用自己,直到在数据库中创建并找到
Customer
,在数据库中它将用于创建
Order

一种方法是直到在数据源中找到
Customer

因此,
Order
创建脚本可能如下所示:

// 1-create-order.js
module.exports = function(app) {
    app.dataSources.mongoDs.autoupdate('Order', function(err) {
        if (err) throw err;
        var customerId = null;
        function addOrder(customerName, obj) {
            if (customerId === null) {
                app.models.Customer.findOne(
                    {where: {name: customerName}}, function(err, customer) {
                    if (err) throw err;
                    if (customer !== null) {
                        customerId = customer.id;
                    }
                });
                setTimeout(addOrder, 1000, customerName, obj);
                return;
            }

            obj.customerId = customerId;
            app.models.Order.findOrCreate({where: obj}, obj
            , function(err, order) {
                if (err) throw err;
            });
        }
        addOrder('Bob', {amount: 42});
    });
}

因此,函数
addOrder
将使用
setTimeout
不断调用自己,直到
Customer
被创建并在数据库中找到,它将用于创建
Order

我在。在调用回调之前,它是否会阻止其他启动脚本的执行?是的,它就是这样做的。我在中看到了这一点,但我不理解回调的作用。在调用回调之前,它是否会阻止其他启动脚本的执行?是的,它就是这样做的。请不要使用这种方法。如果您的引导脚本是异步的,则它必须具有异步
(app,cb)
签名,并且它还将使您的代码和生活更轻松。请不要使用这种方法。如果你的引导脚本是异步的,它必须有异步的
(app,cb)
签名,这也会让你的代码和生活变得更简单。