讲讲 JavaScript 的事件循环机制。
五个经典回答示范
JS 是单线程,事件循环负责调度异步任务。每轮循环先执行同步代码,调用栈清空后把微任务队列全部执行完——Promise.then、queueMicrotask 属于微任务;然后取一个宏任务执行,比如 setTimeout 回调,执行完再清一轮微任务。所以同一时刻注册的 Promise.then 永远先于 setTimeout 执行。
我除了讲浏览器端模型,会对比 Node 的一套:Node 有六个阶段,timers、poll、check(setImmediate)等,process.nextTick 优先级最高。实践上我用它解释过两个问题:为什么 await 后面的代码像回调一样插入微任务;为什么在轮询密集的循环里用 setTimeout 让出主线程能避免页面卡死。
我会强调事件循环的动机:单线程避免 DOM 竞态,异步 IO 避免阻塞渲染。讲清三个细节:任务队列按来源区分、渲染时机在宏任务之间且与 rAF 的关系、微任务清空期间插入的微任务也要处理。落到工程:长任务切片、isInputPending、scheduler.yield,理解事件循环最终服务于交互流畅。
经典输出题:Promise.resolve().then 与 setTimeout(fn,0) 顺序——微任务先;async 函数 await 后的代码进微任务;再加 requestAnimationFrame 的时机问题——rAF 在渲染前执行,介于宏任务之后、绘制之前。做这类题先画循环图再标注入队时机,不会乱。
『事件循环就是 JS 的多线程机制,setTimeout 到时间就会准时执行,所以可以用它做精确计时。』——点评:两个硬伤——JS 单线程,事件循环恰恰不是多线程;定时器只在调用栈空闲且轮到该宏任务时执行,精度很差。概念错误比不知道扣分更重。
- 打开 模拟练习,选择「前端开发」方向,限时 3 分钟作答本题。
- 对照上方答题框架,逐点检查:哪些要素没覆盖、哪里表达啰嗦。
- 用自己项目的真实经历替换框架中的占位内容,重讲一遍并录音回听。
这类题在真实面试中常被追问细节,
建议进入限时模式练一遍。