宏任务和微任务执行顺序
- 初始执行栈:JavaScript 代码是单线程执行的,首先执行主线程上的同步代码,形成执行栈。
- 宏任务队列:宏任务包括
script
(整体代码)、setTimeout
、setInterval
、setImmediate
(仅 Node.js 环境)、I/O
操作、UI rendering
等。当执行栈中的同步代码执行完毕后,会从宏任务队列中取出一个宏任务放入执行栈执行。
- 微任务队列:微任务包括
Promise.then
、process.nextTick
(仅 Node.js 环境)、MutationObserver
等。在一个宏任务执行完后,会检查微任务队列,将微任务队列中的所有任务依次放入执行栈执行,直到微任务队列为空,然后再从宏任务队列中取出下一个宏任务执行,如此循环,这就是事件循环机制。
代码示例及执行分析
console.log('1');
setTimeout(() => {
console.log('2');
Promise.resolve().then(() => {
console.log('3');
});
});
Promise.resolve().then(() => {
console.log('4');
});
console.log('5');
- 首先执行同步代码,输出
1
,5
。
- 同步代码执行完毕,此时宏任务队列中有
setTimeout
回调函数这个宏任务,微任务队列中有 Promise.then
回调函数这个微任务。
- 先执行微任务队列,输出
4
。
- 微任务队列执行完毕,从宏任务队列中取出
setTimeout
回调函数放入执行栈执行,输出 2
。
setTimeout
回调函数执行过程中又产生了一个微任务 Promise.then
,放入微任务队列。
setTimeout
回调函数执行完毕,再次检查微任务队列,执行微任务,输出 3
。
最终输出顺序为:1
,5
,4
,2
,3
。