我正在使用Node / Express / Mongodb / Mongoskin
构建应用程序我有这段代码来更新文档集合:
db.collection('invoices').find().toArray(function(err, dbDocs) {
if (err) throw err;
// Change one, none or several fields named 'paid' in the fetched invoices array
...
// Loop trough the changed dbDocs and use it to update the database.
for (var i = 0, j = dbDocs.length; i < j; i += 1) {
db.collection('invoices').update({_id:dbDocs[i]._id}, {$set:{ paid: dbDocs[i].paid }}, function(err, result) {
if (err) throw err;
// Trigger a redirect after the last iteration.
if (!err && (i === dbDocs.length - 1)) {
console.log('"i" is right now: ', i);
res.redirect('/superadmin/fakturor');
}
});
}
});
这不起作用,因为update()函数正在进行回调,并且当该回调最终触发时,for循环已经完成,这意味着重定向将被调用四次。 我希望重定向被称为ONCE,即在最后一次迭代之后并且没有错误。
如何重写此代码才能使其正常工作?
答案 0 :(得分:1)
首先应注意i = dbDocs.length
:i == dbDocs.length-1
现在,试试这个:
for (var i = 0; i < dbDocs.length; i += 1) {
(function (i) {
db.collection('invoices').update({ _id: dbDocs[i]._id }, { $set: { paid: dbDocs[i].paid } }, function (err, result) {
if (err) throw err;
// Trigger a redirect after the last iteration.
if (!err && (i == dbDocs.length-1)) {
console.log('i: ', i);
res.redirect('/superadmin/fakturor');
}
});
})(i)
}
}
答案 1 :(得分:1)
这是async
library的典型用例,您可以使用一些辅助函数来处理并发问题。
您可以使用async.each(arr, iterator, callback)
,它会在阵列的每个成员上调用iterator()
。完成所有迭代器后,它将调用callback
函数。
var async = require('async');
var updateDoc = function (elem, cb) {
db.collection('invoices').update({_id:elem._id}, {$set:{ paid: elem.paid }}, cb);
}
var done = function (err) {
if (err)
return console.error(err.message);
res.redirect('/superadmin/fakturor');
}
async.each(dbDocs, updateDoc, done);