以前看koa文檔是koa是洋蔥模型,裏面用到的await,next。話很少說,直接貼圖吧
實際await就是這樣的執行邏輯。
先看一段代碼:promise
async function async1() { console.log("async1 start"); await async2(); console.log("async1 end"); } async function async2() { console.log("async2"); await async3() } async function async3() { await async4() console.log('async3') } async function async4() { await async5() console.log('async4') } async function async5() { console.log('async5') } async1(); console.log('start') // 執行結果 // async1 start // async2 // async5 // start // async4 // async3 // async1 end
分析下爲什麼是這樣的:
前面執行結果其實都很容易寫出來
async1 start
async2
碰見await async2,那麼緊跟在await async2 後面的那些代碼就會延遲執行了。
有人說,由於await是promise的語法糖,因此實際緊跟await後面的代碼能夠理解成
new Promise().then(的回調函數來執行)
鵝,,,多是這樣的,或許這樣也好記好理解一些。
仍是按照洋蔥模型來理解執行順序吧。
第一個await async2 後面的代碼先放着,一會再回來執行
ps:何時再回來執行呢?
答曰:等到沒有遇到新的await後,而且非await的同步代碼也執行完了後。
因此執行順序是:
await async2 --> await async3 --> await async4 --> await async5
-->執行非await的同步代碼
-->反過來執行await async5緊跟後面的被阻塞的代碼
...
-->反過來執行await async2緊跟後面的被阻塞的代碼koa
再看一段結合setTimeout異步的代碼異步
async function async1() { console.log("async1 start"); await async2(); console.log("async1 end"); setTimeout(() => { console.log('timer1') }, 0) } async function async2() { setTimeout(() => { console.log('timer2') }, 0) console.log("async2"); } async1(); setTimeout(() => { console.log('timer3') }, 0) console.log("start") // 執行結果 // 'async1 start' // 'async2' // 'start' // 'async1 end' // 'timer2' // 'timer3' // 'timer1'
這裏setTimeout都延遲了0秒,因此按照eventLoop的宏任務,按照宏隊列循環的前後來執行。
執行await async2()時,內部有一個timer2的setTimeout,因此列爲宏1,
執行同步代碼時候,碰見一個timer3的setTimeout,列爲宏2,
按照await緊跟在後面的代碼的洋蔥執行邏輯,timer1,列爲宏3async
因此setTimeout的執行順序就是:
time2-->timer3-->timer1函數