2017-11-11 203 views
4

我发现在某些情况下运行异步等待可能会慢很多。为什么在同时运行它们时异步等待比承诺慢得多

<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。 但在现实中,我得到:

总(承诺):0.25毫秒

总(的await):2.065毫秒

此外,页面加载后,如果我点击“ usingPromises'或'usingAwait'按钮,我可以得到类似的结果。 (均单独运行时速度快)

总(承诺):0.060000000026775524毫秒

总(的await):0.08999999999650754毫秒

但如果我点击 '两个' 按钮时, 'await'版本比promises版本慢3-4倍。

我有一个真正的应用程序在初始化时运行了许多promise/async-await函数,我发现将一些异步等待函数替换为它们的“相等”承诺版本可以减少大量的加载时间(〜200ms) 。

有人可以解释这是为什么吗?是否异步等待也使用相同的作业队列作为承诺(微任务)?是否应该使用承诺的最佳实践而不是异步等待?

  • 在Chrome 62在Mac上运行

感谢

+0

实际上,在Mac上运行Chrome,async-await在这里速度要快得多:'Total(await):0.07500000000004547 ms'和'Total(promises):0.75 ms'。可能是硬件相关的事情。 Async-Await在内部使用Promises。 – NikxDa

+0

注意:调用'runBoth'会给出扭曲的结果,因为承诺解决方案是在事件队列中排序的:所以人们可以先用'console.log'打印另一个,然后就是'console'。日志“会给第二个带来额外的延迟。如果你将'runBoth'定义为'Promise.resolve()。then(usingAwait).then(usingPromises)',那已经是一个改进了。 – trincot

回答

4

你的第一个结果,与按钮Both运行的时候,是一种误导。承诺解决方案在microtask事件队列中排序:所以我们可以在console.log之前先打印另一个,但是console.log会给第二个承诺带来额外的延迟,因为它发生在创建第二个承诺和处理它解析度。

这应该已经是一种进步,如果你将定义runBoth为:

Promise.resolve().then(usingAwait).then(usingPromises) 

现在都承诺将在microtasks创建,并第一个将被解决和处理在创建第二承诺之前。这将导致更公平的比较,其中console.log不是在任何时间测量的。