for循环内的promise是如何工作的?

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)代码块内的该步骤之后添加。

我将非常感谢您解释此功能如何工作。

Ion*_*zău 5

非常有趣的问题!我认为这里代码的重要部分是Promise.race(...)尽快解决其中一个承诺得到解决,它就会得到解决。

\n

我添加了一个sleep带有随机因子(最多 6 秒)的函数,以更好地可视化其工作方式。

\n

预期的功能是:我们总是希望并行执行 20 个 Promise,一旦一个完成,队列中的下一个就会执行。

\n

从视觉上看,这看起来像这样,在下面的示例中,对于 3 和 10 个承诺 \xe2\x80\x93 的限制,您可以注意到在每个时刻都有 3 个活跃的承诺(除了它们结束时):

\n
PromiseID  | Start                 End |\n0          [====]\n1          [==]\n2          [======]\n3             [==========]\n4               [====]\n5                 [================]\n6                    [==]\n7                       [====]\n8                        [======]\n9                            [========]\n
Run Code Online (Sandbox Code Playgroud)\n

创建随机延迟的代码如下:

\n

\r\n
\r\n
PromiseID  | Start                 End |\n0          [====]\n1          [==]\n2          [======]\n3             [==========]\n4               [====]\n5                 [================]\n6                    [==]\n7                       [====]\n8                        [======]\n9                            [========]\n
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n

\n

将迭代数组的 20 多个项目(为什么不是全部 100 个???)

\n
\n

开始时,如图所示,它不会迭代所有 100 个项目,而是迭代前 20 个项目,然后循环暂停await Promise.race(...)(因为executing.length >= poolLimit迭代 20 个项目后将为 true)。

\n

一旦承诺被履行,它将被从executing数组中删除executing.splice(executing.indexOf(e), 1)删除。

\n

我认为当有延迟(await sleep(...))时事情会变得更加清晰,以便我们可以模拟真正的异步操作(例如数据库请求等)。

\n

如果还有其他不清楚的地方,请告诉我。

\n