在 JavaScript 中,任务的执行分为 同步任务 和 异步任务 。异步任务又进一步分为 宏任务(Macro Task) 和 微任务(Micro Task) 。
同步任务
同步任务是按照代码顺序依次执行的任务,会阻塞后续代码的执行,直到当前任务完成。
异步任务
异步任务不会阻塞后续代码的执行,他们会在未来某个时间点执行
宏任务
宏任务是指那些在事件循环中被放入"宏任务队列"的任务。宏任务的执行通常会触发一次完整的事件循环迭代。通常包括:
setTimeout
和setInterval
:定时器任务。setImmediate
(Node.js环境):立即执行的任务。requestAnimationFrame
(浏览器环境):用于浏览器重绘和重排的任务。- I/O操作(Node.js环境):文件读取、网络请求等。
宏任务的特点:
- 宏任务的执行会触发一次完整的事件循环迭代。
- 宏任务队列中的任务按照先进先出(FIFO)的顺序执行。
- 每次事件循环迭代中,宏任务队列中的任务会依次执行,直到队列为空。
微任务
微任务是指那些在事件循环中被放入"微任务队列"的任务。微任务的执行优先级高于宏任务,且会在当前执行栈清空后立即执行。常见的微任务包括:
Promise.then()
、Promise.catch()
、Promise.finally()
process.nextTick
(Node.js)MutationObserver
(浏览器)
微任务的特点:
- 微任务的执行优先级高于宏任务。
- 微任务队列中的任务会在当前执行栈清空后立即执行,而不是等待事件循环的下一次迭代。
- 微任务队列中的任务会按照先进先出(FIFO)的顺序执行,直到队列为空。
事件循环的执行顺序
- 执行所有的同步任务
- 执行所有的微任务
- 执行一个宏任务
- 重复步骤2和3直至所有的任务完成
示例:
js
console.log("1. 同步代码开始");
setTimeout(() => { // 宏任务
console.log("2. 宏任务:setTimeout");
});
Promise.resolve().then(() => { // 微任务
console.log("3. 微任务:Promise.then");
});
console.log("4. 同步代码结束");
输出结果:
js
1. 同步代码开始
4. 同步代码结束
3. 微任务:Promise.then
2. 宏任务:setTimeout
总结
- 宏任务 :执行优先级较低,通常涉及事件循环的完整迭代,如
setTimeout
、setInterval
、setImmediate
等。 - 微任务 :执行优先级较高,会在当前执行栈清空后立即执行,如
Promise
的回调、MutationObserver
、queueMicrotask()
等。 - 执行顺序:事件循环会先执行同步代码,然后执行微任务队列,最后执行宏任务队列。