SailsJS如何编写非异步Model.CRUD函数?

时间:2014-04-05 15:03:09

标签: sails.js

我的应用中有一个父子模型。 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: []
    }
}

};

1 个答案:

答案 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操作期间创建该模型。