await 的執行順序

以前看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函數