题目如下
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')
而 v8 和 node10 产出的结果有所不同。
v8 运行结果????
node10 运行结果????
先说下 async/await 原理????
- async 声明的函数,其返回值必定是 promise 对象,如果没有显式返回 promise 对象,也会用 Promise.resolve() 对结果进行包装,保证返回值为 promise 类型
- await 会先执行其右侧表达逻辑(从右向左执行),并让出主线程,跳出 async 函数,而去继续执行 async 函数外的同步代码
- 如果 await 右侧表达逻辑是个 promise,让出主线程,继续执行 async 函数外的同步代码,等待同步任务结束后,且该 promise 被 resolve 时,继续执行 await 后面的逻辑
- 如果 await 右侧表达逻辑不是 promise 类型,那么 async 函数之外的同步代码执行完毕之后,会回到 async 函数内部,继续执行 await 之后的逻辑
— 摘自 LucasHC
看回题目的代码,同步任务执行下来打印出
script start
async1 start
async2
promise1
script end
同步任务结束后将跑回去执行 await 出来的东西,既然所有的 async 函数返回都是一个 promise,所以 async function async2() {console.log('async2')}
应该返回的是一个 Promise.resolve()
,此时将 resolve 后的then(() => {})
扔进去微任务列表,而微任务列表中已经有一个微任务了 ???? then(function(){console.log('promise2')})
,所以先执行打印出promise2
,再执行then(() => {})
,然后 await 的代码才执行结束,进而执行下面的代码打印出async1 end
。
而以上是 node10+ 的理解,如果放在 v8,则会将 async function async2() {console.log('async2')}
理解为一个同步任务,也就是 await async2()
等同于await console.log('async2')
,所以直接走 await 之后的逻辑打印出async1 end
,再跑微任务打印出promise2
。
如果手动添加 async2
的返回结果为Promise.resolve()
,v8 则和 node 结果一致。