Jon*_*ych 12 javascript asynchronous async-await es6-promise
上下文:我需要进行大量可并行化的异步调用(想想大约300到3000个ajax调用).但是,我不想通过立即调用它们来拉紧浏览器或服务器.我也不想按顺序运行它们,因为它需要很长时间才能完成.我决定一次运行五个左右,并导出此功能:
async function asyncLoop(asyncFns, concurrent = 5) {
// queue up simultaneous calls
let queue = [];
for (let fn of asyncFns) {
// fire the async function and add its promise to the queue
queue.push(fn());
// if max concurrent, wait for the oldest one to finish
if (queue.length >= concurrent) {
await queue.shift();
}
}
// wait for the rest of the calls to finish
await Promise.all(queue);
};
Run Code Online (Sandbox Code Playgroud)
其中asyncFns是一个可迭代的(尚未调用的)异步函数.
问题:这是有效的,但我发现,最老的是第一个完成的并不总是如此.我想修改函数,以便它使用Promise.race等到第一个promise成功,然后从那里继续.但是,我不知道要删除哪个承诺:
// if max concurrent, wait for the first one to finish
if (queue.length >= concurrent) {
await Promise.race(queue);
// ??? get race's completed promise
// queue.splice(queue.indexOf(completed), 1);
}
Run Code Online (Sandbox Code Playgroud)
如果我只知道完成哪一个的索引,我可以将它拼接出队列(我现在更像是一个集合).看起来我不能从竞赛归来的派生者那里得到最初的承诺.建议?
“从队列中删除”步骤应该由已完成的承诺本身(使用then)而不是依赖于从 返回的承诺发生Promise.race。看来这是唯一的办法了。
async function asyncLoop(asyncFns, concurrent = 5) {
// queue up simultaneous calls
let queue = [];
let ret = [];
for (let fn of asyncFns) {
// fire the async function, add its promise to the queue, and remove
// it from queue when complete
const p = fn().then(res => {
queue.splice(queue.indexOf(p), 1);
return res;
});
queue.push(p);
ret.push(p);
// if max concurrent, wait for one to finish
if (queue.length >= concurrent) {
await Promise.race(queue);
}
}
// wait for the rest of the calls to finish
await Promise.all(queue);
};
Run Code Online (Sandbox Code Playgroud)
Npm 模块:https : //github.com/rxaviers/async-pool
感谢@Dan D.,他在发布后不久删除了答案:
let [completed] = await Promise.race(queue.map(p => p.then(res => [p])));
Run Code Online (Sandbox Code Playgroud)
这将为队列中的每个元素创建一个承诺,当承诺完成时,将返回承诺。然后,通过竞速,您将获得首先完成的承诺。
最初在completed或周围没有括号p。由于p是一个诺言并具有一种then方法,因此该诺言再次被链接起来,返回了诺言的已解决价值,而不是诺言(因此不起作用)。我认为这就是删除答案的原因。通过将promise包装在数组中,然后使用Array Destructuring分配,可以防止其再次链接,从而获得promise。