最近,有篇名爲 《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行的順序有問題。bash
再耐心地往下看文章,反覆地看了幾遍 async1 end 和 promise2 誰先誰後,仍是沒法理解爲什麼在chrome瀏覽器中,promise2 會先於 async1 end 輸出。babel
而後,看到評論區,發現也有人提出了相同的疑惑。@rhinel提出,在他的72.0.3622.0(正式版本)dev(64 位)的chrome中,跑出來的結果是 async1 end 在 promise2 以前。異步
隨即我想到了一種可能,JS的規範可能會在將來有變化。因而,我用本身的react工程試了一下(工程中的babel-loader版本爲7.1.5。.babelrc的presets設置了stage-3),結果與個人理解一致。當前的最新版本 chromeV71,在這裏的執行順序上,的確存在有問題。
因而,我也在評論區給做者留了言,進行了討論。@rhinel最後也證明,其實最近才發佈經過了這個順序的改進方案,這篇 《Faster async functions and promises》 詳細解釋了這個改進,以及實現效果。不久以後,做者也在他文章的最後,補充了咱們討論的結果,供讀者參考。
最後,我想說的是,本文雖然只是由一道面試題引伸出的,對瀏覽器執行順序的思考、討論與驗證的過程。但正是由於有了這些過程,才讓更多的思想得以碰撞,概念進一步得以理解,規範得以明瞭。
有機會的話,但願能有與更多的同道,多多交流。
PS:歡迎關注個人公衆號 「超哥前端小棧」,交流更多的想法與技術。