异步mongodb更新循环中最后一次迭代后的重定向

Redirection after last iteration in a loop of asynchronous mongodb updates

本文关键字:迭代 重定向 最后一次 mongodb 更新 循环 异步      更新时间:2023-12-23

我正在用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循环时,这意味着重定向将被调用四次。我希望重定向被调用一次,即在最后一次迭代之后,并且没有错误。

如何重写此代码以使其工作?

首先注意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)
}
}

这是async库的一个典型用例,您可以从中使用一些辅助函数来处理并发问题。

您可以使用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);