Node.js 服务变慢时,如何确认事件循环被同步代码阻塞?
结合事件循环延迟、CPU 栈和请求阶段耗时定位 Node.js 卡顿,给出 monitorEventLoopDelay 的纳秒转毫秒示例,说明统计窗口、采样局限和下游等待不能混为同一根因。
运行时与调度专题面试题第 1 页,显示第 1–41 题,共找到 41 道完整解析,可继续按分类、标签与关键词缩小范围。
按稳定语义路径排序
结合事件循环延迟、CPU 栈和请求阶段耗时定位 Node.js 卡顿,给出 monitorEventLoopDelay 的纳秒转毫秒示例,说明统计窗口、采样局限和下游等待不能混为同一根因。
说明事件循环 close callbacks 只涉及部分资源关闭回调,区分 socket 生命周期、普通 EventEmitter 同名事件和自定义流实现,避免从事件名字推导固定阶段或业务成功。
比较同线程切片、工作线程、独立进程和外部作业的适用边界,说明数据传输、线程池、并发配额、取消和结果关联,避免把 async 或无限 fork 当作 CPU 优化。
以 fs.readFile 回调为具体上下文比较 setImmediate 与零延时定时器,说明 poll 到 check 的关系、定时器阈值,以及同步注册、await 续体和自定义事件的区别。
围绕“JSON.parse 一个超大请求体为什么也会阻塞 Node.js 事件循环,有哪些缓解方式”给出直接结论、机制拆解、可复现验证、常见误区与追问,重点覆盖必须指出 JSON 解析是同步 CPU 操作且给出流式解析或限制体积等方案。
围绕“如何用 perf_hooks 的 monitorEventLoopDelay 量化 Node.js 事件循环延迟”给出直接结论、机制拆解、可复现验证、常见误区与追问,重点覆盖需要说明启用 histogram、读取 mean/p99 等指标并解读 lag 含义。
通过分段求和示例展示如何保存游标与累计结果、在片段间安排 setImmediate,说明首片仍同步执行、总复杂度不变,以及片段预算、取消和不可拆分计算的限制。
按回调职责解释 timers、pending callbacks、idle/prepare、poll、check 和 close callbacks,说明 libuv 1.45 后的定时器调整,并区分阶段图、nextTick 和 Promise 微任务。
解释 poll 处理就绪 I/O 与等待新事件的职责,说明空队列、setImmediate、定时器期限和活动句柄如何影响等待,并区分操作系统高效等待与长 JavaScript 回调阻塞。
围绕“Node.js 进程什么时候自然退出?哪些未决的句柄或定时器会阻止退出”给出直接结论、机制拆解、可复现验证、常见误区与追问,重点覆盖需要解释事件循环在无可执行回调且无 ref 句柄时退出,及 unref 的作用。
从业务是否需要等待时间阈值或只是拆分当前工作出发选择调度 API,说明 setImmediate 的让出机会、定时器漂移、微任务饥饿和 CPU 卸载之间的区别。
围绕“Node.js 的 setTimeout 为什么无法保证精确的毫秒级触发,最小延迟和影响因素有哪些”给出直接结论、机制拆解、可复现验证、常见误区与追问,重点覆盖需要说明事件循环调度与其他阶段耗时造成延迟下限,而非承诺精确唤醒。
解释顶层注册时计时阈值和启动过程如何影响观察,给出独立 CommonJS 脚本用于记录顺序,说明重复结果不是保证,并区分 I/O 回调、ESM 与真实业务依赖。
围绕“Node.js 中给定时器调用 unref() 后进程行为有什么变化,典型用途是什么”给出直接结论、机制拆解、可复现验证、常见误区与追问,重点覆盖需要说明 unref 使该 timer 不再计入活跃句柄从而允许进程退出及监控类典型用途。
围绕“async_hooks 的 init、before、after、destroy 四个回调分别在异步资源生命周期的什么”给出直接结论、机制拆解、可复现验证、常见误区与追问,重点覆盖必须逐一说明四个钩子的触发点及 before/after 可能多次出现的原因。
围绕“Node.js 的 async_hooks 模块能追踪什么,为什么它被标记为实验性但仍被广泛使用”给出直接结论、机制拆解、可复现验证、常见误区与追问,重点覆盖需要说明它能给每个异步资源分配 asyncId 并触发 init/before/after/destroy 回调,及性能与稳定性代价。
围绕“AsyncLocalStorage 如何在 Node.js 中实现跨异步调用的请求级上下文(如 traceId)传递”给出直接结论、机制拆解、可复现验证、常见误区与追问,重点覆盖需要说明 run 建立上下文、getStore 在后续异步回调中取值的机制。
围绕“哪些写法会导致 AsyncLocalStorage 的上下文在 Node.js 中丢失,比如事件监听或连接池复用”给出直接结论、机制拆解、可复现验证、常见误区与追问,重点覆盖必须指出 emit 绑定的是 emit 时刻而非注册时刻上下文、资源复用导致串上下文等丢失场景。
围绕“在 Node.js 里做请求上下文传递,为什么优先 AsyncLocalStorage 而不是第三方 cls 或 z”给出直接结论、机制拆解、可复现验证、常见误区与追问,重点覆盖必须从官方维护、性能与对 async/await 的正确支持论证选型。
围绕“Node.js 的 AsyncResource 类解决什么问题,自定义异步资源(如手写队列)为什么要显式使用它”给出直接结论、机制拆解、可复现验证、常见误区与追问,重点覆盖需要说明用户态异步抽象不会自动纳入 async_hooks 追踪需用 AsyncResource.runInAsyncScope 绑定。
围绕“Node.js 中 executionAsyncId 和 triggerAsyncId 分别代表什么,如何用它们还原”给出直接结论、机制拆解、可复现验证、常见误区与追问,重点覆盖必须区分当前执行栈所属资源与触发创建该资源的资源,并说明因果链还原方式。
围绕“Node.js EventEmitter 的 captureRejections 选项解决了异步监听器里的什么问题”给出直接结论、机制拆解、可复现验证、常见误区与追问,重点覆盖需要说明 async 监听器 rejection 默认变 unhandledRejection 而该选项自动转为 error 事件。
围绕“设计一个 Node.js 内部模块时,什么时候应该继承 EventEmitter 而不是直接回调或返回 Promis”给出直接结论、机制拆解、可复现验证、常见误区与追问,重点覆盖回答要按事件多次发生、多订阅者、生命周期事件的标准给出选择依据。
围绕“为什么 Node.js 约定 EventEmitter 的 'error' 事件没有监听器时会直接抛出异常”给出直接结论、机制拆解、可复现验证、常见误区与追问,重点覆盖需要说明 error 事件的特殊待遇设计意图及不监听导致进程崩溃的后果。
围绕“Node.js 的 events.on() 把 EventEmitter 转成异步迭代器,适用于什么场景,背压如何处”给出直接结论、机制拆解、可复现验证、常见误区与追问,重点覆盖需要说明用 for await 消费事件的场景及内部缓冲与溢出行为。
围绕“Node.js EventEmitter 监听器里的 this 指向什么,箭头函数和普通函数有何差别”给出直接结论、机制拆解、可复现验证、常见误区与追问,重点覆盖需要说明普通函数监听器的 this 绑定到 emitter 而箭头函数保留外层词法 this。
围绕“Node.js EventEmitter 的 'newListener' 事件能在什么场景派上用场,使用时有什么坑”给出直接结论、机制拆解、可复现验证、常见误区与追问,重点覆盖必须给出懒初始化、统计等用途及在 newListener 内再绑监听器导致递归的坑。
围绕“在 Node.js 循环里反复给同一个 EventEmitter 绑 once 监听器,为什么可能内存泄漏,如何规避”给出直接结论、机制拆解、可复现验证、常见误区与追问,重点覆盖需要说明等待触发期间监听器持续累积占内存及用 AbortSignal 或复用 emitter 的规避。
围绕“Node.js 中对 once 注册的监听器调用 removeListener 时应该传原函数还是包装函数”给出直接结论、机制拆解、可复现验证、常见误区与追问,重点覆盖需要说明 emitter 对 once 监听器保存原函数引用故传原函数即可移除的语义。
围绕“Node.js EventEmitter 的 prependListener 与 on 在什么场景下有意义,比如要保”给出直接结论、机制拆解、可复现验证、常见误区与追问,重点覆盖需要说明监听器按注册顺序同步执行及 prepend 控制顺序的用途。
围绕“为什么用匿名箭头函数注册的 EventEmitter 监听器常常 removeListener 失败”给出直接结论、机制拆解、可复现验证、常见误区与追问,重点覆盖必须指出移除依赖同一函数引用及 once 包装后的引用差异。
围绕“Node.js 的 EventEmitter.emit 是同步还是异步派发?这对监听器里的异常有什么后果”给出直接结论、机制拆解、可复现验证、常见误区与追问,重点覆盖必须明确 emit 同步按注册顺序调用监听器且未捕获异常会冒泡中断后续监听器。
围绕“Node.js 中 async 函数里 await 一个 Promise 后,后续代码作为什么类型的任务恢复执行”给出直接结论、机制拆解、可复现验证、常见误区与追问,重点覆盖需要说明 await 之后的续体以微任务形式排入队列及其对执行顺序的影响。
围绕“在 fs 回调等 I/O 回调里创建的 Promise.then 和 setImmediate 谁先执行”给出直接结论、机制拆解、可复现验证、常见误区与追问,重点覆盖回答需要围绕必须利用 poll 阶段后先清空微任务再进入 check 的规则判断微任务先执行。
围绕“Node.js 中 new Promise 的 executor 是同步还是异步执行,这对错误捕获有什么影响”给出直接结论、机制拆解、可复现验证、常见误区与追问,重点覆盖必须明确 executor 同步执行且其抛错转为 rejection,区别于 then 回调的微任务时机。
围绕“在 Node.js 中嵌套的 Promise.then 链与多个并行 Promise 的回调按什么顺序交错执行”给出直接结论、机制拆解、可复现验证、常见误区与追问,重点覆盖回答要按 FIFO 队列逐次入队的规则推演链式与并行 then 的交错顺序。
围绕“Node.js 中每个事件循环阶段结束后微任务队列是如何被清空的”给出直接结论、机制拆解、可复现验证、常见误区与追问,重点覆盖需要说明每个阶段回调执行完即清空 nextTick 与微任务队列,而非整个循环结束才执行。
围绕“Node.js 的 queueMicrotask() 与 process.nextTick、Promise.reso”给出直接结论、机制拆解、可复现验证、常见误区与追问,重点覆盖必须比较三者进入的队列及错误处理行为差异,说明 queueMicrotask 属标准微任务队列。
围绕“官方建议哪些场景使用 process.nextTick,例如保证回调总是异步的 API 设计”给出直接结论、机制拆解、可复现验证、常见误区与追问,重点覆盖必须给出统一同步/异步回调时机、在事件派发前让调用者先绑监听器等官方场景。
围绕“为什么在 Node.js 中递归调用 process.nextTick 会导致 I/O 饿死,而递归 setImme”给出直接结论、机制拆解、可复现验证、常见误区与追问,重点覆盖需要解释 nextTick 在阶段间持续清空阻塞循环推进,setImmediate 每轮只执行一次。
围绕“process.nextTick 队列和 Promise 微任务队列都清空时谁先执行?为什么”给出直接结论、机制拆解、可复现验证、常见误区与追问,重点覆盖必须给出 nextTick 队列优先于 Promise 微任务队列的结论并解释队列分离的实现。