2017-11-11 190 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不是在任何時間測量的。

相關問題