我的应用中有一个父子模型。 Parent.create接收parent_name和我想要添加到Parent模型的子数组,以下流程描述了该函数:
1)创建父对象
2)创建所有孩子
3)使用更新的子数组
保存父级问题是 Parent.create 可能是异步,保存到父级的'created_children'数组是空的(因为它不会等到父.create finish。
如何使Model.create依赖(或同步)?
请参阅下面的代码(我评论了有缺陷的部分// BUG:EMPTY ARRAY !!!!!!!!!!):
create: function(req, res, next) {
var childrenInput = req.param('children');
var parentObj = {
name: req.param('parent_name')
};
Parent.create(parentObj, function parentCreated(err, parent) {
if (err) {
return res.redirect('/parent/new');
}
// assign children
var created_children = new Array();
for(var i=0; i < childrenInput.length; i++) {
var childObj = {
name: parentObj.childrenInput[i],
parent_id: parent.id
};
// create child
Child.create(childObj, function childCreated(err, child) {
if (err) {
for(var j=0; j < created_children.length; j++) {
Child.destroy(created_children[j].id, function childDestroyed(err) {
if (err)
{
// BIG ERROR
return next(err);
}
});
}
return res.redirect('/parent/new');
}
// add created child
created_children.push(child.id);
}) // end of Child.create;
} // end of for;
// save created children to parent
parent.children = created_children.slice();
parent.save(function(err, c) {
if (err)
{
// TODO: FUNCTION TO DESTROY ALL CHILDREN
return next(err);
}
});
return res.redirect('/parent/show/' + parent.id);
});
},
家长模式
module.exports = {
schema: true,
attributes: {
name: {
type: 'string',
required: true,
unique: true
},
children: {
type: 'array',
defaultsTo: []
}
}
};
答案 0 :(得分:1)
对阵列执行异步操作可能会非常痛苦。我建议使用像async这样的模块,它为异步代码提供类似于同步的功能。然后,您可以将代码重写为:
Parent.create(parentObj, function parentCreated(err, parent) {
if (err) {
return res.redirect('/parent/new');
}
// You only really need this for error handling...
var created_children_ids = new Array();
// Create an array of child instances from the array of child data
async.map(
// Array to iterate over
childrenInput,
// Iterator function
function(childObj, callback) {
Child.create(childObj, function childCreated(err, child) {
if (err) {return callback(err);}
created_children_ids.push(child.id);
// 'null' indicates no error
return callback(null, child);
});
},
// Callback for when loop is finished.
// If any run of the iterator function resulted in the
// callback being called with an error, it will immediately
// exit the loop and call this function. Otherwise the function
// is called when the loop is finished, and "results" contains
// the result of the mapping operation
function (err, results) {
if (err) {return destroyChildren();}
// Save the children to the parent
parent.children = results;
parent.save(function(err, c) {
if (err) {return destroyChildren();}
return res.redirect('/parent/show/' + parent.id);
});
function destroyChildren(err) {
Child.destroy({id: created_children_ids}).exec(function() {
// Respond with an error
return res.serverError(err);
});
}
}
);
});
请注意,如果您正在使用Sails v0.10,则可以使用actual associations绑定父记录和子记录,并在常规中使用parent.children.add(childObj)
(这是一个同步操作)在调用parent.save()
之前循环。使用对象调用.add
将导致在save
操作期间创建该模型。