在 Node.js 环境中,setImmediate() 与 setTimeout() 这两类定时器在执行时机上存在哪些差异?请说明它们各自的行为特征。
考察说明
考查对 Node.js 事件循环中定时器阶段和 check 阶段的理解,以及两类定时器回调触发时机的区别。
回答思路
- 【回答框架 1】setImmediate() 的回调在事件循环的 check 阶段执行,而 setTimeout() 的回调在 timers 阶段执行。两者都用于延迟执行,但所属阶段不同,因此执行顺序受调用上下文影响。
- 【回答框架 2】在 I/O 回调外部(如主模块),setTimeout(fn, 0) 与 setImmediate(fn) 的执行顺序不确定,取决于进程启动耗时与事件循环状态;在 I/O 回调内部,setImmediate() 总是先于 setTimeout() 执行,因为 check 阶段在 timers 阶段之前。
- 【回答框架 3】setTimeout() 的延迟时间最小值为 1ms,即使设置为 0 也会至少延迟 1ms;而 setImmediate() 没有延迟参数,会在当前轮询阶段结束后立即执行。
- 【回答框架 4】此外,process.nextTick() 又不同,它不属于事件循环阶段,而是在当前操作完成后立即执行,优先于任何定时器回调。
- 【关键点 1】setImmediate() 回调在 check 阶段执行,setTimeout() 回调在 timers 阶段执行。
- 【关键点 2】在 I/O 回调内,setImmediate() 先于 setTimeout(0) 执行;在主模块中顺序不确定。
- 【关键点 3】setTimeout() 最小延迟 1ms,setImmediate() 无延迟参数。
- 【关键点 4】process.nextTick() 独立于事件循环,优先级最高。
- 【易错点 1】误以为 setTimeout(0) 一定先于 setImmediate() 执行,实际在主模块中顺序不固定。
- 【易错点 2】忽略最小延迟 1ms,以为 setTimeout(0) 立即执行。
- 【易错点 3】混淆 setImmediate() 与 process.nextTick() 的优先级。