返回

揭秘 JavaScript 宏任务和微任务,深入理解事件循环

前端

宏任务与微任务

在 JavaScript 中,所有的任务都分为两大类:宏任务和微任务。宏任务包括:

  • script :脚本代码,即浏览器加载的 JavaScript 文件。
  • setTimeout() :定时器函数,用于在指定时间后执行回调函数。
  • setInterval() :定时器函数,用于每隔一段时间执行回调函数。
  • setImmediate() :立即执行函数,用于在当前事件循环的末尾执行回调函数。
  • requestAnimationFrame() :动画帧请求函数,用于在浏览器下一次重绘之前执行回调函数。

微任务包括:

  • Promise.then() :Promise 对象的 then() 方法,用于在 Promise 对象状态改变后执行回调函数。
  • Promise.catch() :Promise 对象的 catch() 方法,用于在 Promise 对象状态变为 rejected 后执行回调函数。
  • Promise.finally() :Promise 对象的 finally() 方法,用于在 Promise 对象状态改变后(无论状态如何)执行回调函数。
  • MutationObserver :MutationObserver 对象,用于观察 DOM 树的变化,并在变化发生后执行回调函数。
  • MessageChannel :MessageChannel 对象,用于在不同的线程之间传递消息,并在消息被接收后执行回调函数。

事件循环

事件循环是 JavaScript 引擎处理任务的机制。它是一个不断循环的过程,主要分为以下几个步骤:

  1. 执行同步任务:在事件循环的每个阶段,首先会执行同步任务,即主线程上的任务。
  2. 执行微任务:在同步任务执行完毕后,会执行微任务。微任务的执行顺序与它们的创建顺序一致。
  3. 更新渲染树:在微任务执行完毕后,浏览器会更新渲染树,即根据 DOM 树和 CSS 样式表生成新的页面。
  4. 执行宏任务:在渲染树更新完毕后,会执行宏任务。宏任务的执行顺序与它们的创建顺序一致。

执行时机

在事件循环中,宏任务和微任务的执行时机如下:

  • 宏任务 :宏任务会在当前事件循环的末尾执行,即在所有微任务执行完毕后。
  • 微任务 :微任务会在当前事件循环的每个阶段执行,即在同步任务执行完毕后,在宏任务执行之前。

应用场景

宏任务和微任务在实际开发中有着广泛的应用场景,例如:

  • 延迟任务执行 :可以使用 setTimeout() 或 setInterval() 函数来延迟任务的执行。例如,可以在页面加载完成后,使用 setTimeout() 函数延迟执行一个函数来初始化页面。
  • 动画 :可以使用 requestAnimationFrame() 函数来创建动画效果。requestAnimationFrame() 函数会确保动画在浏览器下一次重绘之前执行,从而实现流畅的动画效果。
  • 异步编程 :可以使用 Promise 对象来实现异步编程。Promise 对象可以表示一个异步操作的结果,并允许你对结果进行处理。例如,可以在发送 AJAX 请求后,使用 Promise 对象来等待请求结果,并在结果返回后执行回调函数。
  • DOM 操作 :可以使用 MutationObserver 对象来观察 DOM 树的变化。MutationObserver 对象可以在 DOM 树发生变化后执行回调函数,从而实现对 DOM 树的动态更新。
  • 消息传递 :可以使用 MessageChannel 对象在不同的线程之间传递消息。MessageChannel 对象可以创建两个端口,一个端口用于发送消息,另一个端口用于接收消息。当消息被接收后,会执行回调函数。

结论

宏任务和微任务是 JavaScript 中两个重要的概念,它们决定了异步代码的执行顺序。宏任务包括 script、setTimeout()、setInterval()、setImmediate() 和 requestAnimationFrame(),而微任务包括 Promise.then()、Promise.catch()、Promise.finally()、MutationObserver 和 MessageChannel。宏任务会在当前事件循环的末尾执行,即在所有微任务执行完毕后,而微任务会在当前事件循环的每个阶段执行,即在同步任务执行完毕后,在宏任务执行之前。宏任务和微任务在实际开发中有着广泛的应用场景,例如延迟任务执行、动画、异步编程、DOM 操作和消息传递。