首先來看一道考察JS執行機制的面試題,原題是今日頭條的前端面試題,我稍微進行了一點改造:html
async function async1() { console.log( 'async1 start' ) await async2() console.log( 'async1 end' ) } async function async2() { new Promise( function ( resolve ) { console.log( '11' ) resolve(); }).then( function () { console.log( '22' ) }) } 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 11 promise1 script end 22 promise2 async1 end setTimeout
由於題目是變幻無窮的,平常開發中的狀況也是多種多樣的,正確理解了其中的執行規律才能更好地開發,固然若是你獲得的結果是同樣的而且可以自圓其說那也就不必看下去了,若是你還對這個結果有點懵那就聽聽個人理解吧。node
事實上,咱們的JS代碼用同步和異步這兩種劃分方式來決定執行的前後順序顯然是不夠的,從而有了另外一種劃分方式,具體誰提出來的我就沒考證了,大致上你們是這樣分的:面試
由於咱們上面的面試題是前端面試題,因此咱們討論的都是瀏覽器環境下的表現,node環境下的event loop貌似有些不同,這裏就不討論了。segmentfault
既然前端談到了JS是單線程的,同時只能處理一個任務,而咱們又將各類各樣的任務分爲了宏任務和微任務,那到底哪一種任務先執行了,這個運行邏輯就是event loop的判斷邏輯。promise
先說說個人理解,再來印證上面代碼的運行順序:瀏覽器
說回上面的面試題,咱們模擬event loop來首先給他們歸個隊多線程
async本質上是加上了Generator函數而且內置了執行器的一個語法糖,而且async函數返回的是Promise對象。惟一須要注意的是await後面不管接的是同步代碼仍是異步代碼都要等他們執行完畢才能執行await結果以後的代碼。而且通過驗證,當遇到await語句時是從右到左先執行的await後面的代碼,而後才交出線程的控制權直到await等待的結果運行完畢。異步
整體上,算是能對上面那個題目的執行過程有了一個能自圓其說的解釋,只是吧,爲何規則是這樣的呢?這些規則怎麼證僞呢?這是我查資料的時候最糾結的問題。後來跟同事交流了以後吧,以爲也不必糾結,畢竟最終的解釋器是C寫的,不懂規則能夠去看源碼啊,但是我看不懂啊,哈哈。。。因此,既然你們大部分人都是這麼說,也能說得通,暫且先記着吧,至少,仍是可以解釋平常中形形色色代碼的運行規律的。async
看了幾篇不一樣觀點的文章以後從新梳理一下event loop的順序:
參考文章中有幾篇文章比我講的生動一些,沒看懂的能夠參考一下,我主要是梳理一下本身的理解,有不一樣想法的歡迎交流。