最近,有篇名爲 《8張圖幫你一步步看清 async/await 和 promise 的執行順序》 的文章引發了個人關注。前端
做者用一道2017年「今日頭條」的前端面試題爲引子,分步講解了最終結果的執行緣由。其中涉及到了很多概念,好比異步的執行順序,宏任務,微任務等等,同時做者限定了執行範圍,以瀏覽器的 event loop 機制爲準。下面是原題的代碼:react
async function async1 () { console.log('async1 start'); await async2(); console.log('async1 end'); } async function async2 () { console.log('async2'); } console.log('script start'); setTimeout(function () { console.log('setTimeout'); }, 0); async1(); new Promise(function (resolve) { console.log('promise1'); resolve(); }).then(function () { console.log('promise2'); }); console.log('script end');
緊接着,做者先給出了答案。並但願讀者先行自我測試。面試
script start async1 start async2 promise1 script end promise2 async1 end setTimeout
我在看這道題的時候,先按照本身的理解寫出告終果。chrome
script start async1 start async2 promise1 script end async1 end promise2 setTimeout
這裏須要先簡單地說一些 event loop 的概念。segmentfault
另外,還有 async/await 的概念。promise
再說說我對這道題的理解。瀏覽器
回過頭對比與做者的答案,發現第6和第7行的順序有問題。babel
再耐心地往下看文章,反覆地看了幾遍 async1 end 和 promise2 誰先誰後,仍是沒法理解爲什麼在chrome瀏覽器中,promise2 會先於 async1 end 輸出。異步
而後,看到評論區,發現也有人提出了相同的疑惑。@rhinel提出,在他的72.0.3622.0(正式版本)dev(64 位)的chrome中,跑出來的結果是 async1 end 在 promise2 以前。async
隨即我想到了一種可能,JS的規範可能會在將來有變化。因而,我用本身的react工程試了一下(工程中的babel-loader版本爲7.1.5。.babelrc的presets設置了stage-3),結果與個人理解一致。當前的最新版本 chromeV71,在這裏的執行順序上,的確存在有問題。
因而,我也在評論區給做者留了言,進行了討論。@rhinel最後也證明,其實最近才發佈經過了這個順序的改進方案,這篇 《Faster async functions and promises》 詳細解釋了這個改進,以及實現效果。不久以後,做者也在他文章的最後,補充了咱們討論的結果,供讀者參考。
最後,我想說的是,本文雖然只是由一道面試題引伸出的,對瀏覽器執行順序的思考、討論與驗證的過程。但正是由於有了這些過程,才讓更多的思想得以碰撞,概念進一步得以理解,規範得以明瞭。
有機會的話,但願能有與更多的同道,多多交流。
講道理,async/await 已經出來挺久了,但在近期的面試中,凡是問及異步操做,面試者的回答都仍是 Promise,甚至知道 async/await 都不多,看來還有待進一步普及。並非說 Promise 有什麼很差,只是以爲 async/await 用着挺爽的,但願能有更多的人用吧。只有用了,才能進一步理解,產生更多的思考。
因此,這兩天翻出了以前寫的關於什麼是async函數,及其相較於 Promise 的優點。從新整理了一下,原文請前往《細說async/await相較於Promise的優點》。
但願對你有幫助,也期待進一步的交流,感謝!
PS:歡迎關注個人公衆號 「超哥前端小棧」,交流更多的想法與技術。