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

时间:2013-11-28 16:15:15

标签: javascript node.js mongodb express

我正在使用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,即在最后一次迭代之后并且没有错误。

如何重写此代码才能使其正常工作?

2 个答案:

答案 0 :(得分:1)

首先应注意i = dbDocs.lengthi == 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);
相关问题