event loop的执行顺序:
- 一开始整个脚本作为一个宏任务执行
- 执行过程中同步代码直接执行,宏任务进入宏任务队列,微任务进入微任务队列
- 当前宏任务执行完出队,检查微任务列表,有则依次执行,直到全部执行完
- 执行浏览器UI线程的渲染工作
- 检查是否有Web Worker任务,有则执行
- 执行完本轮的宏任务,执行宏任务队列的下一个,依此循环,直到宏任务和微任务队列都为空
微任务包括:MutationObserver
、Promise.then()
或reject()
、Promise
为基础开发的其它技术,比如fetch API
、V8
的垃圾回收过程、Node
独有的process.nextTick
。
宏任务包括:script、script
、setTimeout
、setInterval
、setImmediate
、I/O
、UI rendering
。
下面是一道执行顺序的综合题
来自一个问答的题目
async function asyncl() {
console.log('asyncl start')
await async2()
console.log('asyncl end')
}
async function async2() {
console.log('async2 start')
return new Promise((resolve, reject) =>{
resolve()
console.log('async2 promise')
})
}
console.log('script start')
setTimeout(function() {
console.log('setTimeout')
}, 0)
asyncl()
new Promise(function(resolve) {
console.log('promise1')
resolve()
}).then(function() {
console.log('promise2')
}).then(function() {
console.log('promise3')
})
console.log('script end')
event loop的执行顺序过程分析
- 刚开始整个脚本作为第一次宏任务来执行,我们将它标记为宏1,从上至下执行
- 遇到asyncl和async2函数先声明,执行同步代码console.log('script start')
- 遇到setTimeout放到下一个宏任务队列
- asyncl被调用,执行asyncl中的同步代码console.log('asyncl start')
- 遇到await,后面代码被阻断,async2被调用,执行async2中的同步代码console.log('async2 start')
- 遇到Promise,此时Promise被resolve()因此状态改为了resolved,执行Promise中的同步代码console.log('async2 promise'),async2执行完
- 再遇到Promise,执行Promise中的同步代码console.log('promise1'),遇到Promise.resolve()状态改为了resolved
- 跳出Promise,往下执行,碰到promise.then这个微任务,将其加入微任务队列1
- 又碰到promise.then这个微任务,将其加入微任务队列2
- 再执行同步代码console.log('script end'),到此处执行完,再回头执行微任务队列console.log('promise2')和console.log('promise3')
- 最后回到await被阻断的代码执行console.log('asyncl end')
注意点: async函数中await后被阻断的代码,等待的时间是有限的,微任务执行队列不是无限制时间执行
总结
首先先按照顺序执行同步代码,再执行微任务队列(promise),回来看是否存在被await阻断的同步代码及微任务,执行完,再执行宏任务队列(setTimeout)。
个人的一些浅见,写的不好请轻喷!!!!欢迎一起交流!!!!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。