首先是一道今日頭條的面試題:(據說是今日頭條的而且已經爛大街了)javascript
1 async function async1() { 2 console.log( 'async1 start' ) 3 await async2() 4 console.log( 'async1 end' ) 5 } 6 7 async function async2() { 8 console.log( 'async2' ) 9 } 10 11 console.log( 'script start' ) 12 13 setTimeout( function () { 14 console.log( 'setTimeout' ) 15 }, 0 ) 16 17 async1(); 18 19 new Promise( function ( resolve ) { 20 console.log( 'promise1' ) 21 resolve(); 22 } ).then( function () { 23 console.log( 'promise2' ) 24 } ) 25 26 console.log( 'script end' )
這個題我認爲的順序和瀏覽器的順序一開始並不同,讓我一度覺得瀏覽器出了問題。java
首先須要瞭解promise,否則後面就很難理解下去。參見:http://es6.ruanyifeng.com/#docs/promisees6
簡單來說若是一個函數前面帶了async那麼,函數的返回值一定是一個promise的對象。若是返回值不是promise對象,會自動的去包裝爲一個promise對象。面試
await能夠算是async wait簡寫。等待async執行結果。promise
回到代碼中,顯而易見首先打印的內容是‘script start’,不須要解釋。瀏覽器
而後就是setTimeout,雖然時間是0可是隻有在這一輪事件循環的底部或者是事件隊列爲空纔會當即執行,很明顯既不是底部,事件隊列也還未執行完成。async
下一個執行到async1();函數
在async1中首先打印‘async1 start’,而後遇到await,await會阻塞後面的代碼,先執行async外部的代碼,因此會接着打印‘async2’;spa
以前的await中斷了當前async的執行,因此下一個執行的就是promise,promise是直接調用同步代碼,因此接着就是‘promise1’;code
由於會優先執行同步代碼,因此接下來就是打印‘script end’;
執行完畢回到promise接着執行then打印‘promise2’,以後再次回到前面繼續執行resolve,可是由於參數爲空,因此打印‘undefined’;(promise執行順序,具體參見:http://es6.ruanyifeng.com/#docs/promise)
這個時候await async2()執行結束,繼續async1後面的代碼,打印‘async1 end’;
至此因此的事件隊列執行結束
前面說了,事件隊列爲空纔會執行setTimeout。
因此正確的順序爲:
script start async1 start async2 promise1 script end promise2 async1 end setTimeout
有錯誤的話歡迎指正。