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