等待已经履行承诺的性能开销是多少?

sbm*_*kur 6 javascript asynchronous node.js promise async-await

在进行代码审查时,我最近遇到过这样的代码块:

const promises = [];
const data = [];
for (let piece of pieces) {
  for (let chunk of piece) {
    promises.push(execute(chunk)); //execute returns a promise which is not yet fulfilled
  }
  data = await Promise.all(promises);
}
Run Code Online (Sandbox Code Playgroud)

pieces是一个数组数组.请注意,由于某些约束,我们不能同时使用await所有Promise,因此这种类型的分块.

在我的反馈中,我写道,这似乎是一个反模式,因为我们也在等待在前几次迭代中解决的 Promises ,以下是处理这种情况的正确方法:

const data = [];
for (let piece of pieces) {
  const promises = [];
  for (let chunk of piece) {
    promies.push(execute(chunk)); //execute returns a promise which is not yet fulfilled
  }
  data.push(... await Promise.all(promises));
}
Run Code Online (Sandbox Code Playgroud)

最后,data两种情况都是一样的.

我理解data这两种情况都是如何填充的.我想知道等待已经履行的承诺(在第一个代码块中发生的)的性能开销是多少,并且它是否重要?

Ber*_*rgi 1

开销是微不足道的 - 它需要迭代已经履行的承诺,检查它,取出数据并将其放入结果数组中。假设本机承诺,我希望对此进行优化,并且不需要往返事件循环,如果数组中有thenables,那么所有这些都需要解析为承诺,并且需要异步等待该承诺,采取对承诺作业队列造成影响。

与函数中实际完成的异步工作相比,处理时间的开销并不显着execute

然而,无论开销有多小,第一个版本的代码的问题是它的运行时复杂性是二次的:每次都Promise.all需要迭代整个数组。promises你拥有的块越多,效果就越明显。我同意您的评论反馈,并会推荐该代码的第二个版本。

  • @EricHaynes 准确地说,它通过微任务队列,而不是整个事件循环。`await undefined` (或 `Promise.resolve()`)不能替代 `requestIdleCallback` 或 `setImmediate` (如果需要,您可以将其包装在 Promise 中);`while (true)await Promise.resolve()` 将冻结浏览器。 (2认同)