使用 Async/Await 与 Promise.all 与 for 循环

sto*_*neb 5 javascript asynchronous node.js promise async-await

以下是我目前对事情的理解:

for 循环中的 async/await 应暂停执行,直到 Promise 解析为止,这意味着在该行完成之前不会发生循环的下一次迭代。

考虑以下数组:

const data = [];
for (let i = 0; i <= 100000; i++) {
    data.push(i);
}
Run Code Online (Sandbox Code Playgroud)

方法 1:在 for 循环中等待 Promise

async function method1() {
  const startTime = new Date();
  console.log('start:', startTime);

  for (const item in data) {
    await new Promise(resolve => {
      if (item % 3 === 0) {
        resolve({});
      } else {
        resolve(item)
      }
    });
  }

  const endTime = new Date();
  console.log('finish:', endTime);
  console.log('total time:', endTime-startTime);
}
Run Code Online (Sandbox Code Playgroud)

因为它需要顺序执行 Promise 才能继续循环,所以我认为使用 Promise.all 将是一种性能增强,可以更大程度地利用异步处理:

方法 2:Promise.all 跟随 for 循环

async function method2() {
  const promises = [];
  const startTime = new Date();
  console.log('start:', startTime);

  for (const item in data) {
    const promise = new Promise(resolve => {
      if (item % 3 === 0) {
        resolve({});
      } else {
        resolve(item)
      }
    });

    promises.push(promise);
  }

  await Promise.all(promises);
  const endTime = new Date();
  console.log('finish:', endTime);
  console.log('total time:', endTime-startTime);
}
Run Code Online (Sandbox Code Playgroud)

我的推理:当每个先前创建的 Promise 尝试解析时,循环将继续产生新的 Promise。所以在我看来,方法 1 = 阻塞...而方法 2 = 更少的阻塞。

当我在 repl.it 上运行这两个方法时,我发现方法 1 实际上更快,几乎快了 2 倍。有人能解释一下这是为什么吗?难道不应该反过来吗?

Dra*_*ang 3

我的猜测是你解决得太快了,所以循环占据了执行时间,因为 method2 有两个循环:一个用于推送到数组,一个用于promise.all完成,而 method1 只有一个循环,所以你的感觉“几乎是两倍” ”实际上理论上是正确的。

尝试假装actual async operation点赞new Promise(resolve => setTimeout(resolve, 200)),你应该会得到你期望的结果