是否有实现let res = Promise.all([...p], limit)
的方法/模式?
res
结算之后,p
应该得到解决
limit=3
承诺应在并行 limit
个解析器并行运行。特别是最后一点让我头疼。
我目前的解决方案是将promises-array拆分为limit
大小的块并链接它们。这里的缺点是第二组不会开始,直到第1组的所有Promise都已解决。
答案 0 :(得分:3)
我提出了创建n = limit
链的想法,这些链并行运行并且只要有承诺就附加:
let promises = [];
for(let i=0; i<11; i++) promises[i] = () => {
console.log('Construct:',i);
return new Promise(resolve => {
setTimeout(function() {
console.log('Resolve:',i);
resolve(i);
}, Math.round(Math.random() * (2000 - 500) + 2000));
});
}
function parallelLimit(promiseFactories, limit) {
let result = [];
let cnt = 0;
function chain(promiseFactories) {
if(!promiseFactories.length) return;
let i = cnt++; // preserve order in result
return promiseFactories.shift()().then((res) => {
result[i] = res; // save result
return chain(promiseFactories); // append next promise
});
}
let arrChains = [];
while(limit-- > 0 && promiseFactories.length > 0) {
// create `limit` chains which run in parallel
arrChains.push(chain(promiseFactories));
}
// return when all arrChains are finished
return Promise.all(arrChains).then(() => result);
}
parallelLimit(promises, 4).then(console.log);
很高兴阅读您的意见和建议:)
答案 1 :(得分:1)
bluebird-as扩展程序中的sequenceWithParallelism
功能似乎专为您想要的功能而设计。如上所述,它使用bluebird进行实现,但我在sequenceWithParallelism
函数的实际内容中没有看到任何蓝鸟特定的内容,因此您可以摘录该函数并在您自己的代码中使用它,如:
sequenceWithParallelism(limit, f => f())([..p])
.then(function () {
});
奇怪的是,这个功能似乎并不是为了解决所有承诺的结果,所以如果你需要,你可能需要做一些调整。
答案 2 :(得分:0)
我最终编写了以下代码:
const parallelLimit = (asyncFuncs, limit) => {
return new Promise((res, rej) => {
let open = 0
const rets = [], errs = []
const exec = () => { while(ff.length && open < limit) ff.shift()() }
const ff = asyncFuncs.map(f => {
return () => {
open++
f()
.then(r => rets.push(r))
.catch(e => errs.push(e))
.finally(_ => {
open--
exec()
if(!ff.length && !open)
return errs.length ? rej(errs) : res(rets)
})
}
})
exec()
})
}
// test:
const t = Date.now()
const funcs = [...Array(10).keys()].map(idx => {
return () => {
return new Promise((res, rej) => {
setTimeout(() => {
console.log(`idx: ${idx} time: ${Date.now() - t}`)
res(idx)
}, 1000)
})
}
})
parallelLimit(funcs, 2)
.then(res => console.log(`then ${res.join(',')}`))
.catch(errs => console.log(`catch ${errs.join(',')}`))