如何避免在JavaScript Promises中计算循环迭代

时间:2017-06-16 23:02:32

标签: javascript loops promise es6-promise

我最近开始使用promises,所以我可以等到我在执行下一个函数之前用x个记录更新数据库。我发现自己计算循环迭代,以便在正确的时间解决承诺。例如:

var updateAccounts = function(accounts) {
  var promise = new Promise(function(resolve, reject) {
      var counter = 0;
      accounts.forEach(function(account) {

        db.collection('accounts').update({
          name: account.name
        }, {
          $set: {
            balance: account.balance
          }
        });
        counter++
        if (counter == accounts.length) {
          resolve('accounts updated');
        }
      });
    }
  });
  return promise;
}

有没有办法等到循环完成而不计算迭代次数?它只是感觉有点hacky,但我不确定它是否真的是一个问题。

2 个答案:

答案 0 :(得分:4)

根据MDN

  

Promise对象表示异步操作的最终完成(或失败)及其结果值。

基本上这意味着Promise应该跟踪单个异步操作的结果。

但是,在您的示例中,您已在一个db.collection('accounts').update(...)内执行了多个异步操作(即Promise)。你不得不诉诸于互动计数来追踪完整性,而不是依赖于这样做的承诺。

要解决此问题(双关语:D),您的每个异步请求都应该有自己的Promise

由于您有多个更新,因此有多个承诺,因此您可以使用Promise.all来捕获所有承诺成功完成的时间。

这里是您的代码示例的快速改编:

var updateAccounts = function(accounts) {
    var promises = [];
    accounts.forEach(function(account) {
        var promise = new Promise(function(resolve, reject) {
            db.collection('accounts').update({
              name: account.name
            }, {
              $set: {
                balance: account.balance
              }
            });
        });
        promises.push(promise);
    });

    Promise.all(promises).then(function(arrPromises) { 
        console.log("All promises resolved.");
    }).catch(function(failedPromise) {
        console.log("Something failed.");
    });

}

我的示例中唯一缺少的是resolve成功执行后调用db.collection('accounts').update(...)。更新成功完成后,您必须调用resolve,或者如果更新失败,则必须调用reject。这就是它已经完成的承诺。

我的代码示例在没有它的情况下无法工作,但是从原始代码示例中不清楚哪个应该指定db.collection('accounts').update(...)的回调 - 所以我省略了它

答案 1 :(得分:0)

你可以尝试一下foreach吗?



var updateAccounts = function(accounts) {
  var promise = new Promise(function(resolve, reject) {
      ...
      accounts.forEach(function(account) {
        ...
      });
    <---Here<--
    }
  });
  return promise;
}
&#13;
&#13;
&#13; 在循环中检查foreach的完成似乎很奇怪。也许你想确保帐户数组有一些元素?您也可以在循环外检查零或非零长度。