我正在使用引导脚本来创建一些模型和关系。例如,我可能有这个:
+-------+ +----------+
| Order | --belongsTo--> | Customer |
+-------+ +----------+
我想创建:1 Customer
和 1 Order
属于该Customer
。
我知道环回引导按文件名字母顺序执行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;
});
});
};
对于Order
,我首先找到Customer
并创建订单 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};
^
我宁愿在创建Order
之前不添加一小段等待,因为这看起来很不稳定,并且不能保证父模型的存在,尤其是在数据源碰巧很慢的情况下。
我也不想将所有这些代码合并到一个文件中,因为我的真实项目有很多模型,这将导致一个巨大的无法维护的文件。
有没有好方法可以等待父模型自动迁移完成,然后再开始子模型?
您可以使用额外的回调参数创建异步引导脚本,并在脚本准备就绪时调用它。
例:
module.exports = function (app, cb) {
var db = app.dataSources.db;
// update all database models
db.autoupdate(function (err) {
if (err) throw err;
cb();
});
};
一种方法是继续循环,直到在数据源中找到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
。