前端面试 P021:事件循环、微任务与渲染机会
Showing the original in Chinese (China)
来源:方格前端讲面试 · 21.事件循环(Event Loop)完整解析,24 分 28 秒。
回看定位:09:23 任务分类 · 10:44 微任务 · 14:26 浏览器示例 · 20:16 Node.js
把运行中的代码和等待执行的回调分开
一个 JavaScript agent 的同步代码按调用栈执行;网络、定时器等等待能力由宿主提供。等待完成并不直接打断当前函数,相关回调要按宿主与语言规则进入可执行的队列。
在常见浏览器示例中,可以先按“执行当前任务 → 微任务检查点 → 合适时机更新渲染 → 后续任务”的模型分析。微任务检查会继续处理期间新增的微任务,直到相应队列排空。
console.log('start');
setTimeout(() => console.log('timer'), 0);
Promise.resolve().then(() => console.log('promise'));
queueMicrotask(() => console.log('microtask'));
console.log('end');
// 输出:start、end、promise、microtask、timer
Promise 构造器的 executor 同步执行,then/catch/finally 的反应回调异步执行。微任务是调度类别,不代表回调一定耗时很短。
视频的两个简化需要修正
UI 渲染不是普通的单一“宏任务队列里的一个回调”。 浏览器有任务来源、微任务检查点和渲染更新步骤;是否渲染还取决于时机、页面状态等,并非每个任务后必然画一帧。
事件循环不会自动解决 CPU 阻塞。 一个耗时同步循环持续运行时,UI 仍然可能冻结;无限追加微任务也可能让定时器和渲染长期没有机会。需要拆分工作、让出执行机会或选择 Worker。
Node.js 不能直接套一张浏览器图
Node.js 有 timers、poll、check 等阶段,并有 process.nextTick 队列和 Promise 微任务的相应处理规则。nextTick 与 Promise 并非同一个队列;入口是 CommonJS 还是 ES 模块也会影响一些输出题的先后。
做题时先标明环境和版本,再追踪入队位置;不要用“永远谁的优先级高”替代具体执行阶段。规范背景见 HTML:事件循环 与 Node.js:事件循环。