微任务和宏任务有什么区别?

在前端开发中,微任务(Microtasks)和宏任务(Macrotasks)代表了两种不同的异步任务类型,它们在事件循环(Event Loop)中的执行时机和顺序有所不同。理解它们的区别对于编写高效且行为符合预期的 JavaScript 代码至关重要。

宏任务 (Macrotasks):

  • 定义: 宏任务是浏览器发起的一些异步任务,它们通常包含:

    • setTimeout
    • setInterval
    • setImmediate (Node.js 环境)
    • requestAnimationFrame (浏览器动画)
    • I/O 操作
    • UI 渲染
    • 用户交互事件 (例如:点击、滚动)
  • 执行时机: 每一个宏任务执行完毕后,事件循环会检查微任务队列,并将所有在队列中的微任务执行完毕,然后再执行下一个宏任务。

微任务 (Microtasks):

  • 定义: 微任务是 JavaScript 引擎自身发起的一些异步任务,它们通常包含:

    • Promise.then()Promise.catch()Promise.finally()
    • queueMicrotask()
    • MutationObserver (监听 DOM 变化)
  • 执行时机: 在当前宏任务执行完毕后,立即执行所有在微任务队列中的微任务,然后再执行下一个宏任务。这意味着在一个宏任务中,如果产生了新的微任务,这些微任务会在下一个宏任务开始之前被执行。

关键区别总结:

特性 宏任务 (Macrotasks) 微任务 (Microtasks)
发起者 浏览器或 Node.js 环境 JavaScript 引擎自身
典型示例 setTimeout, setInterval, I/O, UI rendering Promise.then(), queueMicrotask(), MutationObserver
执行时机 每个宏任务之后,执行所有微任务,然后执行下一个宏任务 当前宏任务之后,立即执行所有微任务
队列 宏任务队列 微任务队列

示例说明:

console.log('Start');

setTimeout(() => {
  console.log('setTimeout');
}, 0); // 宏任务

Promise.resolve().then(() => {
  console.log('Promise.then');
}); // 微任务

console.log('End');

输出结果为:

Start
End
Promise.then
setTimeout

解释:

  1. StartEnd 同步执行并打印。
  2. setTimeoutPromise.then 都是异步操作,被添加到各自的队列中。
  3. 尽管 setTimeout 的延迟时间为 0,但它仍然是一个宏任务,会在当前宏任务 (主线程的同步代码) 执行完毕后才执行。
  4. 在当前宏任务执行完毕后,事件循环会检查微任务队列,发现 Promise.then,于是先执行 Promise.then 并打印 Promise.then
  5. 最后,事件循环取出 setTimeout 这个宏任务并执行,打印 setTimeout

理解微任务和宏任务的区别对于控制代码执行顺序、避免竞态条件以及编写高效的异步代码至关重要。 例如,在处理 UI 更新时,使用微任务可以确保在浏览器重新渲染之前完成所有必要的 DOM 操作,从而避免闪烁和性能问题。

posted @ 2024-12-01 06:18  王铁柱6  阅读(57)  评论(0编辑  收藏  举报