宏任务类型
- script 代码
- setTimeout/setInterval
- UI rendering/UI事件
- postMessage,MessageChannel
- setImmediate,I/O(Node.js)
微任务类型
- Promise
- MutaionObserver
- process.nextTick(Node.js)
规则
先执行第1个宏任务,即js整体代码。此过程可能会产生新的宏任务和微任务,按时间顺序,宏任务进入宏任务队列,微任务进入微任务队列。
执行栈清空后,检查微任务队列,有则出队,进入执行栈执行。
执行栈清空后,检查微任务队列,有则出队,进入执行栈执行。
。。。(同上)
执行栈清空后,检查微任务队列,无。
检查宏任务队列,有,则1个宏任务出队入栈。此时新一轮循环开始。
注意:执行微任务的过程仍然可能会产生新的宏任务和微任务,产生新任务后继续入队。
案例
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')
第一轮事件循环:
执行宏任务:打印 script start → async2 end → Promise → script end
执行微任务:打印async1 end → promise1 → promise2
第二轮事件循环:
执行宏任务:打印 setTimeout
此时执行栈、宏任务队列、微任务队列都为空。