我正在研究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);
});
}
我认为正确的方法是立即返回承诺,并即时添加结果,但我不知道如何做到这一点。有什么建议吗?
答案 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)
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;
就像@Tobi说的那样,你可以使用Promise.All ..
但是Promise.all有一个问题!!
如果您的处理阵列有很多项目,那么发送大量项目以及同时执行某些异步工作可能不是最佳的。并且在某些情况下不可能,例如。在节点中一次打开太多文件会导致句柄错误太多。
Bluebird promise库有一个名为map的有用函数,它有一个名为concurrency的选项。这允许你一次处理X个数量的promise。我个人认为带有并发选项的map函数应该是Promise规范的一部分,因为它非常有用。如果不使用并发选项,它将具有与promise.all相同的效果,而无需先创建数组。
在上面的例子中,我创建了20个随机超时,最多1秒。不使用map,执行此操作的最长时间为1秒,因为所有promises将立即执行。但是使用3的并发选项,它一次做3个,你可以看到完成时间超过1秒。