循环中使用promises(节点)

时间:2016-11-03 14:21:44

标签: javascript node.js design-patterns promise

我正在研究NodeJS后端服务,并使用promises加载任何数据。现在,我想制作来自不同来源的项目组合(数组)。我有以下解决方案,但我不认为这是解决这类问题的正确方法。

var results = [];
loop(items, index, data, results).then(function() {
    console.log(results);
});

function loop(items, index, data, results) {
    return utils.getPromise(function(resolve, reject) {
        if (index === items.length) {
            // Stop
            resolve();
        } else {
            doAction(items[index], data).then(function(result) {
                if (result) {
                    mergeResults(results, result)
                } else {
                    loop(items, index + 1, data, results).then(resolve, reject);
                }
            }, reject);
        }
    });
}

function doAction(item, data) {
    return utils.getPromise(function(resolve, reject) {
        item.doIt(data).then(resolve, reject);
    });
}

我认为正确的方法是立即返回承诺,并即时添加结果,但我不知道如何做到这一点。有什么建议吗?

2 个答案:

答案 0 :(得分:6)

您可以使用Promise.all收集承诺中的所有结果。然后使用包含每个承诺的所有单个结果的数组来解析 .all 承诺本身。

  

我认为正确的方法是立即回复承诺

就像你建议的那样,你只需返回承诺并从这些承诺中创建一个数组。在循环之后,您将此数组放入 Promise.all

可能看起来像这样:

var promiseArray = [];
for(var i=0;i<array.length;i++){
    promiseArray.push(doSomethingAsync(array[i]));
}
Promise.all(promiseArray).then(function(responseArray){
    //do something with the results
});

答案 1 :(得分:1)

&#13;
&#13;
function randTimeout(t) {
  return new Promise(function (resolve) {
    setTimeout(function () {
      console.log('time done:' + t);
      resolve();
    }, t);
  });
}

var timeouts = [];
for (var l = 0; l < 20; l ++) {
  timeouts.push(Math.random() * 1000 | 0);
}

console.log('start');
Promise.map(timeouts, function (t) {
  return randTimeout(t);
}, {concurrency: 3}); 
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/bluebird/3.4.6/bluebird.min.js"></script>
&#13;
&#13;
&#13;

就像@Tobi说的那样,你可以使用Promise.All ..

但是Promise.all有一个问题!!

如果您的处理阵列有很多项目,那么发送大量项目以及同时执行某些异步工作可能不是最佳的。并且在某些情况下不可能,例如。在节点中一次打开太多文件会导致句柄错误太多。

Bluebird promise库有一个名为map的有用函数,它有一个名为concurrency的选项。这允许你一次处理X个数量的promise。我个人认为带有并发选项的map函数应该是Promise规范的一部分,因为它非常有用。如果不使用并发选项,它将具有与promise.all相同的效果,而无需先创建数组。

在上面的例子中,我创建了20个随机超时,最多1秒。不使用map,执行此操作的最长时间为1秒,因为所有promises将立即执行。但是使用3的并发选项,它一次做3个,你可以看到完成时间超过1秒。