在JavaScript 中,宏任务微任务和页面渲染的关系

139 阅读2分钟

在JavaScript 中,宏任务微任务和页面渲染的关系

在 JavaScript 中,理解宏任务(Macro Task)、微任务(Micro Task)以及页面渲染之间的关系对于编写高效和响应迅速的应用非常重要。以下是它们之间的关系和工作机制:

宏任务 (Macro Task)

宏任务通常是由事件循环(Event Loop)管理的较大任务单元。常见的宏任务包括:

宏任务(Macro Task)

宏任务通常是由事件循环 (Event Loop)管理的较大任务单元。常见的宏任务包括:

  • setTimeout
  • setInterval
  • setImmediate (Node.js环境)
  • I/O操作
  • UI渲染

事件循环会依次从宏任务队列中取出任务执行,执行完一个宏任务后,会查看是否有需要处理的微任务。

微任务 (Micro Task)

微任务是比宏任务更小的任务单元,会在当前宏任务执行完成后立即执行,但在下一个宏任务开始之前。常见的微任务包括:

  • Promie 的 thencatch回调
  • MutationObserver
  • nextTick

页面渲染

页面渲染是浏览器的一个独立步骤,通常会在宏任务执行之间或微任务队列清空之后进行。为了确保页面能够流畅地更新,浏览器会在执行完一个宏任务并处理完所有微任务后,进行页面渲染。

工作流程

  1. 执行栈(Call Stack):JavaScript 引擎从执行栈中取出任务执行。如果执行栈为空,事件循环会开始工作。
  2. 宏任务队列(Macro Task Queue):事件循环从宏任务队列中取出任务,将其放入执行栈中执行。
  3. 执行宏任务:执行栈执行宏任务。
  4. 处理微任务队列(Micro Task Queue):在当前宏任务执行完成后,事件循环会检查微任务队列,将所有微任务依次放入执行栈中执行,直到微任务队列为空。
  5. 页面渲染:在微任务队列清空后,浏览器会进行页面渲染。
  6. 下一个宏任务:事件循环继续从宏任务队列中取出下一个任务,放入执行栈中执行,循环继续。

示例

console.log('Script start');  
  
setTimeout(() => {  
  console.log('setTimeout');  
}, 0);  
  
Promise.resolve().then(() => {  
  console.log('Promise1');  
}).then(() => {  
  console.log('Promise2');  
});  
  
console.log('Script end');

输出顺序

Script start  
Script end  
Promise1  
Promise2  
setTimeout
  • console.log('Script start')console.log('Script end') 是同步任务,立即执行。
  • setTimeout被放入宏任务队列
  • Promisethen 回调被放入微任务队列。
  • 执行栈为空后,事件循环开始处理微任务队列,依次执行 Promise1Promise2 的回调。
  • 微任务队列清空后,浏览器进行页面渲染(虽然在这个例子中没有明显渲染)。
  • 最后,事件循环从宏任务队列中取出 setTimeout 的回调并执行。
  • 理解这些概念对于调试和优化 JavaScript 代码非常重要,特别是在处理异步操作和确保页面响应性方面。