前言
對於promise、async和await的執行順序,很多人都容易弄混,也有很多人只願意在程序中運用一種,比如我只使用promise,不使用async和await;也有只用async和await,而不是用promise。所以現在來為大家講講一起共存需要注意寫什么?

示例
下面這段promise、async和await代碼,請問控制台打印的順序?
上述,在Chrome 66和node v10中,正確輸出是:
知識點
顯然,這考察的是js中的事件循環和回調隊列。注意以下幾點:
* Promise優先於setTimeout宏任務。所以,setTimeout回調會在最后執行。
* Promise一旦被定義,就會立即執行。
* Promise的reject和resolve是異步執行的回調。所以,resolve()會被放到回調隊列中,在主函數執行完和setTimeout前調用。
* await執行完后,會讓出線程。async標記的函數會返回一個Promise對象
難點
最令人困惑的,就是async1 end在promise2之后輸出
在函數async1中,執行promise(由於async2是async標記的函數,所以默認返回promise對象)會發現resolve(),然后放入回調隊列。
接着執行下方的new Promise中的resolve()輸出promise2,再回來輸出async1 end。
其中,async1函數可以寫成以下方式(便於理解):
流程
1. `console.log('script start')`輸出:`script start`
2. `setTimeout`被放在最后調用
3. 執行`async1`函數,輸出`async1 start`。然后,進入`async2`函數,輸出`async2`,並返回`Promise`對象。回到`async1`,由於`await`,讓出線程,`async2`函數返回的`Promise`放在**回調隊列**。
4. 新new了一個`Promise`對象,輸出`promise1`。其中的`resolve()`被放在回調隊列。
5. `console.log('script end')`輸出:`script end`
6. 執行回調隊列中,`async1`返回的`Promise`對象,對象產生的`resolve`被放入對調隊列。這里不輸出任何值。
7. 執行回調隊列中,下方`Promise`顯式聲明的`resolve`,輸出`promise2`。
8. 執行回調隊列中,由於`async1`函數返回的`promise`對象的`resolve`,輸出`async1 end`。
9. 執行回調隊列中,最后的`setTimeout`,輸出`setTimeout`
10. finish
