上一篇简单分析了async/await背后的原理,接下来分析一个很常见的例子,来说明async/await的执行顺序。
async/await 执行顺序解析
console.log('script start')
async function async1() {
await async2()
console.log('async1 end')
}
async function async2() {
console.log('async2 end')
}
async1()
setTimeout(function() {
console.log('setTimeout')
}, 0)
new Promise(resolve => {
console.log('Promise')
resolve()
})
.then(function() {
console.log('promise1')
})
.then(function() {
console.log('promise2')
})
console.log('script end')
先放答案:(执行环境Chrome v73-v80)
script start
async2 end
Promise
script end
async1 end
promise1
promise2
setTimeout
分析步骤:
- 执行代码,输出script start
- 执行async1(),会调用async2(),然后输出async2 end, 此时async2 已经执行完毕,async2函数会返回一个Promise,在Chome 73版本以后,await Promise 在语义上等于Promise.resolve(async2()).then(await后的逻辑),因此此时会产生一个微观任务进入到micro task queue
- 遇到setTimeout,产生一个宏任务(宏任务和微观任务不理解的可以参考博客)
- 执行Promise,输出Promise。遇到then,又产生一个微任务,同样进入到micro task queue,然后继续执行代码,输出script end
- 这时event loop回去check 微观队列,第一个微观任务就是async1函数await后的逻辑,所以输出:async1 end,这时async1执行完成,同样该微观任务也执行完
- 在进入到宏观任务之前,会确保微观任务队列没有任务,因此继续执行产生的微任务,输出promise1,当前微任务执行完毕,向微任务队列放入新的微任务即“console.log(‘promise2’)”
- 继续检查微任务队列,输出promise2
- 执行宏任务,输出setTimeout
关于浏览器Event Loop 和微观/宏观任务不理解的,可以查相关资料学习,本文也会继续分享Event Loop 和微观/宏观任务的文章。