上下文:我需要进行大量可并行的异步调用(大约 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);
};
其中 asyncFns 是(尚未调用)异步函数的可迭代对象。
问题:这可行,但我发现最老的第一个完成并不总是正确的。我想修改函数以便它使用 Promise.race等到第一个 promise 成功,然后从那里继续。然而,我不知道要删除哪个 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);
}
如果我只知道哪个完成的索引,我可以将它从队列中拼接出来(我猜现在它更像是一个集合)。看起来我无法从 race 返回的派生 promise 中得到最初的 promise 。有什么建议吗?
最佳答案
感谢@Dan D. 在发布后不久删除了他们的答案:
let [completed] = await Promise.race(queue.map(p => p.then(res => [p])));
This creates a promise for each of the elements in the queue that when the promise completes returns the promise. Then by racing those you get the promise that first completed.
completed
或 p
最初没有括号。由于 p
是一个 promise 并且有一个 then
方法,promise 被再次链接,返回 promise 的解析值而不是 promise(因此它不起作用)。我想这就是答案被删除的原因。通过将 promise 包装在一个数组中,然后使用 Array Destructuring assignment ,你可以防止它再次链接,得到 promise 。
关于javascript - 获取在 Promise.race 中完成了哪个 promise,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42896456/