Async - parallel()与函数动态数组

时间:2012-09-18 07:40:01

标签: javascript node.js express mongoose async.js

我正在使用nodejs的优秀caolan“async”模块:

我有这段代码:

exports.manageComments = function(req, res) {
    var toDeleteIds = [];
    var deleteFunctions = [];
    if (req.body.doDelete) {
        toDeleteIds = req.body.doDelete;
    }
    var i;
    for ( i = 0; i < toDeleteIds.length; i++ ) {
        var deleteFunction = function(callback) {
            var id = toDeleteIds[i];
            console.log(id);
            Comment.findOne({_id:id}, function(err, found) {            
                if (!err) found.remove(callback);
            });
        }
        deleteFunctions.push(deleteFunction);
    }
    async.parallel(
        deleteFunctions,
        function(err,results) {
            exports.comments(req, res); //render a view
        }
    );
};

我的数组包含两个元素,但console.log()一直告诉我“未定义”。

我错过了什么?

2 个答案:

答案 0 :(得分:11)

你的问题在于:

    var deleteFunction = function(callback) {
        var id = toDeleteIds[i];

因为在执行每个回调函数时,i将具有与toDeleteIds.length相同的值。闭包不会“捕获”外部变量在创建时的值;它“捕获”对外部变量在执行时具有的任何值的引用(在这种情况下,直到你的for循环完成后才会这样。

为了在创建回调函数时“捕获”i的值,您需要使i成为您调用以创建回调函数的函数的参数。你需要像

这样的东西
    var deleteFunction = makeDeleteFunction(i, callback);

然后在回调之外创建一个单独的函数:

function makeDeleteFunction(i, callback) {
    return function(callback) {
        var id = toDeleteIds[i];
        console.log(id);
        Comment.findOne({_id:id}, function(err, found){            
            if (!err) found.remove(callback);
        });
     };
}

答案 1 :(得分:2)

另一种观点是,如果您不需要在每个被移除的remove文档上触发Mongoose Comment中间件,您可以一次删除所有已识别的注释:

Comment.remove({_id: {$in: toDeleteIds}}, function(err, numRemoved) {
    exports.comments(req, res); //render a view        
}