【问题标题】:SailsJS how to write non-async Model.CRUD functions?SailsJS 如何编写非异步 Model.CRUD 函数?
【发布时间】:2014-04-06 07:34:04
【问题描述】:

我的应用中有父子模型。 Parent.create 接收 parent_name 和我要添加到 Parent 模型的子数组,以下流程描述了该函数:

1) 创建父对象

2) 创建所有子节点

3) 用更新的子数组保存父

问题是 Parent.create 可能是 async,而 'created_children' 数组在保存到 parent 时是空的(因为它不会等到 Parent .create 完成。

如何使 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: []
    }
}

};

【问题讨论】:

    标签: sails.js


    【解决方案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 绑定父记录和子记录,并在调用 @987654325 之前在常规循环中使用 parent.children.add(childObj)(这是一个同步操作) @。使用对象调用 .add 将导致在 save 操作期间创建该模型。

    【讨论】:

    • 在这种情况下没有理由使用mapSeries;它只会让你慢下来。利用 Node 的异步特性并并行运行这些任务!
    • 但问题是如果其中一个异步调用失败,它不会停止整个迭代并且可能不会释放所有资源。如果有 5 个条目,则第 2 个失败,则在调用错误处理程序时,创建的 created_children_ids 只有一个条目,该条目被删除,但其他 3 次迭代并未停止。
    猜你喜欢
    • 1970-01-01
    • 2021-12-19
    • 2021-12-31
    • 2011-10-17
    • 1970-01-01
    • 2020-03-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多