【问题标题】:How much is the performance overhead for awaiting an already fulfilled Promise?等待已经实现的 Promise 的性能开销是多少?
【发布时间】:2019-04-26 14:32:46
【问题描述】:

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

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);
}

这里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));
}

最后,data 在两种情况下都是相同的。

我了解data 在这两种情况下的填充方式。我想知道等待已经实现的承诺(发生在第一个代码块中)的性能开销是多少,是否重要?

【问题讨论】:

  • 这两个代码块根本不一样...第一个的数据最终会比数据中的第二个少
  • 这里的意图还不清楚。当然,如果这是关于聚集到data,那么这两个列表可能都不是那么理想。为了澄清到目前为止我在这里看到的 cmets,示例 1 是“重新分配”data 和 2。是“尝试”累积。不幸的是,在这里真正理解上下文有点“元”。没有上下文,任何答案都没有任何意义。最好让 cmets 冷静下来并让 OP 澄清。
  • 如果你在循环之外使用第二个变体和await data,这将是最快的选择
  • 抱歉@sbmthakur 我被代码的最后一部分分心了,错过了嵌套差异。
  • @CertainPerformance 不,它们仍然是 Promise。

标签: javascript node.js asynchronous promise async-await


【解决方案1】:

开销很小 - 它需要迭代已经实现的承诺,检查它,取出数据并将其放入结果数组中。假设本机承诺,我希望这将得到优化,并且不需要到事件循环的往返,如果您在数组中有 thenable,那么所有这些都需要解析为一个承诺,并且该承诺需要异步等待,采取承诺作业队列的收费。

与在您的 execute 函数中完成的实际异步工作相比,处理时间的开销不会很大。

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

【讨论】:

    猜你喜欢
    • 2016-04-15
    • 2017-09-27
    • 2019-09-04
    • 1970-01-01
    • 2012-12-12
    • 1970-01-01
    • 1970-01-01
    • 2012-05-23
    • 2021-07-26
    相关资源
    最近更新 更多