1

题目如下

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运行结果?

clipboard.png

node10运行结果?
clipboard.png

先说下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结果一致。

clipboard.png


AwesomeHan
125 声望4 粉丝