前端与浏览器 / 进阶

事件循环不只分宏任务和微任务

解释浏览器如何从任务队列取出工作、清空微任务、决定是否渲染,并说明微任务链为什么也会阻塞页面。

微任务也会饿死渲染

微任务执行期间新加入的微任务也会在本轮继续执行。递归 queueMicrotask 或不断续接 Promise,会让浏览器迟迟拿不到渲染机会。 需要让出主线程时,可把非紧急工作拆成多个任务。现代浏览器可用 scheduler.postTask;兼容性要求高时,可组合 MessageChannel、setTimeout 和分片预算。

EXAMPLE / 01Event Loop
console.log('A');
setTimeout(() => console.log('B'), 0);
Promise.resolve().then(() => {
  console.log('C');
  queueMicrotask(() => console.log('D'));
});
console.log('E');

把实现拆成可验证的小块

微任务链过长同样会阻塞输入和渲染

最后回到真实页面检查

视觉更新放到 rAF,重计算则要拆分或移出主线程