为什么在一起运行时,async-await比promises慢得多?

7

我发现在某些情况下,使用async-await可能会更慢。

<html>
  <script>
    function makeAPromise() {
      return Promise.resolve(Math.random());
    }

    function usingPromises() {
      const before = window.performance.now();
      return makeAPromise().then((num) => {
        const after = window.performance.now();
        console.log('Total (promises): ', after-before, 'ms');
        return num;
      })
    }

    async function usingAwait() {
      const before = window.performance.now();
      const num = await makeAPromise();
      const after = window.performance.now();
      console.log('Total (await): ', after-before, 'ms');
      return num;
    }

    function runBoth() {
      usingAwait();
      usingPromises();
    }
    
    runBoth();

  </script>

  <button onclick="usingPromises()">usingPromises</button>
  <button onclick="usingAwait()">usingAwait</button>
  <button onclick="runBoth()">both</button>
</html>

usingPromises中,console.log应该打印类似于usingAwait中的结果。但实际上,我得到了:

Total (promises): 0.25 ms

Total (await): 2.065 ms

此外,在页面加载后,如果我点击“usingPromises”或“usingAwait”按钮,它们各自都会得到类似的结果。(当单独运行时,两者都很快)

Total (promises): 0.060000000026775524 ms

Total (await): 0.08999999999650754 ms

但是,如果我点击“both”按钮,“await”版本比promises版本慢3-4倍。

我有一个真正的应用程序,在初始化时运行许多promises/async-await函数,我发现将某些async-await函数替换为它们的“相等”promises版本可以节省大量加载时间(~200ms)。

有人能解释这是为什么吗?难道async-await不也使用与promises相同的作业队列(微任务)吗?何时应该使用promises而不是async-await的最佳实践是什么?

  • 在Mac上使用Chrome 62

谢谢


1
实际上,在Mac上运行Chrome时,异步等待比起Promise更快:Total (await): 0.07500000000004547 msTotal (promises): 0.75 ms。可能与硬件有关。异步等待在内部使用Promise。 - NikxDa
1
注意:调用runBoth会产生扭曲的结果,因为Promise的解析是按事件队列顺序进行的:因此一个Promise在另一个之前使用console.log打印,而正是这个console.log给第二个Promise带来了额外的延迟。如果您将runBoth定义为Promise.resolve().then(usingAwait).then(usingPromises),那么这已经是一种改进了。 - trincot
1个回答

6
您在运行按钮“Both”时得到的第一个结果是误导性的。承诺的解决方案按照微任务事件队列进行排序:因此,其中一个会在另一个之前使用“console.log”进行打印,但正是这个“console.log”给第二个带来了额外的延迟,因为它发生在第二个承诺创建和处理其解决方案之间。
如果您将“runBoth”定义为以下内容,则已经有所改进:
Promise.resolve().then(usingAwait).then(usingPromises)

现在,两个 promise 都将在微任务中创建。第一个 promise 在创建第二个 promise 前被解决并处理,这将导致更公平的比较,其中 console.log 不会被计入任何时间。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接