我正在使用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()一直告诉我“未定义”。
我错过了什么?
答案 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
}