Kar*_*ren 6 javascript arrays node.js reactjs
在我的程序源代码中我有以下函数(Promise并发限制函数,类似于pLimit):
async function promiseMapLimit(
array,
poolLimit,
iteratorFn,
) {
const ret = [];
const executing = [];
for (const item of array) {
const p = Promise.resolve().then(() => iteratorFn(item, array));
ret.push(p);
if (poolLimit <= array.length) {
const e = p.then(() => executing.splice(executing.indexOf(e), 1));
executing.push(e);
if (executing.length >= poolLimit) {
await Promise.race(executing);
}
}
}
return Promise.all(ret);
}
Run Code Online (Sandbox Code Playgroud)
它工作正常,所以如果我向它传递一个数字数组 [1..99] 并尝试将其乘以 2,它将给出正确的输出 [0..198]。
const testArray = Array.from(Array(100).keys());
promiseMapLimit(testArray, 20, async (value) => value * 2).then((result) =>
console.log(result)
);
Run Code Online (Sandbox Code Playgroud)
代码示例 - js 游乐场。
但我无法理解它的逻辑,在调试过程中我注意到,它以 20 块为单位添加了承诺,并且只有在这之后才进一步:

例如,以下代码块:
for (const item of array) {
const p = Promise.resolve().then(() => iteratorFn(item, array));
ret.push(p);
Run Code Online (Sandbox Code Playgroud)
将迭代数组的 20 多个项目(为什么不是全部 100 个???)
同样在这里:
if (poolLimit <= array.length) {
const e = p.then(() => executing.splice(executing.indexOf(e), 1));
executing.push(e);
Run Code Online (Sandbox Code Playgroud)
它只会向executing数组添加 20 个项目,并且仅在if (executing.length >= poolLimit)代码块内的该步骤之后添加。
我将非常感谢您解释此功能如何工作。
非常有趣的问题!我认为这里代码的重要部分是Promise.race(...)尽快解决其中一个承诺得到解决,它就会得到解决。
我添加了一个sleep带有随机因子(最多 6 秒)的函数,以更好地可视化其工作方式。
预期的功能是:我们总是希望并行执行 20 个 Promise,一旦一个完成,队列中的下一个就会执行。
\n从视觉上看,这看起来像这样,在下面的示例中,对于 3 和 10 个承诺 \xe2\x80\x93 的限制,您可以注意到在每个时刻都有 3 个活跃的承诺(除了它们结束时):
\nPromiseID | Start End |\n0 [====]\n1 [==]\n2 [======]\n3 [==========]\n4 [====]\n5 [================]\n6 [==]\n7 [====]\n8 [======]\n9 [========]\nRun Code Online (Sandbox Code Playgroud)\n创建随机延迟的代码如下:
\nPromiseID | Start End |\n0 [====]\n1 [==]\n2 [======]\n3 [==========]\n4 [====]\n5 [================]\n6 [==]\n7 [====]\n8 [======]\n9 [========]\nRun Code Online (Sandbox Code Playgroud)\r\n\n\n将迭代数组的 20 多个项目(为什么不是全部 100 个???)
\n
开始时,如图所示,它不会迭代所有 100 个项目,而是迭代前 20 个项目,然后循环暂停await Promise.race(...)(因为executing.length >= poolLimit迭代 20 个项目后将为 true)。
一旦承诺被履行,它将被从executing数组中删除executing.splice(executing.indexOf(e), 1)删除。
我认为当有延迟(await sleep(...))时事情会变得更加清晰,以便我们可以模拟真正的异步操作(例如数据库请求等)。
如果还有其他不清楚的地方,请告诉我。
\n| 归档时间: |
|
| 查看次数: |
1357 次 |
| 最近记录: |