微任务与宏任务
微任务(Microtask)和宏任务(Macrotask)是 JavaScript 事件循环(Event Loop)中的两个核心概念,用于描述异步任务的执行顺序和优先级。它们的区别主要体现在任务调度和执行时机的不同。
宏任务: JavaScript 引擎在事件循环的每个“循环周期”中处理的主要任务。
-
setTimeout
和setInterval
的回调 -
DOM 事件(如点击、滚动)
-
I/O 操作:Input/Output 输入/输出操作,是计算机与外部设备或其他系统进行数据交互的过程。简单来说,它是程序读取数据(输入)或写入数据(输出)的行为
-
文件操作:读取本地文件、写入文件。
-
网络请求:向服务器发送 HTTP 请求(如
fetch
、XMLHttpRequest
)。 -
用户交互:监听键盘输入、鼠标点击。
-
数据库操作:查询或修改数据库中的数据。
-
设备通信:与摄像头、打印机等硬件设备交互。
-
-
requestAnimationFrame
(浏览器) -
主线程的同步代码(整体 script 代码本身也是一个宏任务)
-
执行顺序:
每个事件循环中,宏任务队列中的任务会依次执行,每次只执行一个宏任务,执行完成后会检查微任务队列。
微任务:在当前宏任务执行完成后、下一个宏任务开始前立即执行的任务,优先级高于宏任务。
-
Promise.then()
、Promise.catch()
、Promise.finally()
的回调 -
MutationObserver
(监听 DOM 变化) -
queueMicrotask()
函数 -
Node.js 中的
process.nextTick
(优先级最高,但仅在 Node.js 环境) -
微任务的设计是为了让某些高优先级的异步操作(如 Promise 回调)能尽快执行,避免被宏任务(如 UI 渲染、I/O)阻塞,从而提升性能和响应速度。
-
执行顺序:
每执行完一个宏任务后,会清空整个微任务队列(包括微任务执行过程中新产生的微任务),然后再执行下一个宏任务。
事件循环的执行流程
-
执行一个宏任务(如 script 主代码)。
-
执行过程中遇到微任务,将其加入微任务队列;遇到宏任务,加入宏任务队列。
-
当前宏任务执行完毕后,立即依次执行所有微任务(直到微任务队列为空)。
-
浏览器可能进行 UI 渲染。
-
从宏任务队列中取出下一个宏任务,重复上述流程。