詳解promise、async和await的執行順序


前言

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

詳解promise、async和await的執行順序

示例

下面這段promise、async和await代碼,請問控制台打印的順序?

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') 
JavaScript

上述,在Chrome 66node v10中,正確輸出是:

script start
async1 start
async2
promise1
script end
promise2
async1 end
setTimeout
JavaScript

知識點

顯然,這考察的是js中的事件循環和回調隊列。注意以下幾點:
Promise優先於setTimeout宏任務。所以,setTimeout回調會在最后執行。
Promise一旦被定義,就會立即執行。
Promiserejectresolve是異步執行的回調。所以,resolve()會被放到回調隊列中,在主函數執行完和setTimeout前調用。
await執行完后,會讓出線程。async標記的函數會返回一個Promise對象

難點

最令人困惑的,就是async1 endpromise2之后輸出

在函數async1中,執行promise由於async2async標記的函數,所以默認返回promise對象)會發現resolve(),然后放入回調隊列。

接着執行下方的new Promise中的resolve()輸出promise2,再回來輸出async1 end

其中,async1函數可以寫成以下方式(便於理解):

async function async1(){ console.log('async1 start') async2().then( _ => { console.log( 'async1 end ') }) } 
JavaScript

流程

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM