Node.js中setImmediate 和 setTimeout(0) 的区别
作者:光影少年
文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
如果你说的是 Node.js 里的 setImmediate() 和 setTimeout(fn, 0),核心区别在于:它们进入的是不同的 Event Loop 阶段,因此执行顺序取决于代码运行的位置。
先记结论
setTimeout(() => console.log('timeout'), 0);
setImmediate(() => console.log('immediate'));
在主线程(main module)中直接运行时:
顺序不保证,可能是 timeout → immediate,也可能是 immediate → timeout。
但如果是在 I/O 回调里面:
const fs = require('fs');
fs.readFile(__filename, () => {
setTimeout(() => console.log('timeout'), 0);
setImmediate(() => console.log('immediate'));
});
通常是:
immediate timeout
因为 I/O 回调执行在 Event Loop 的 poll 阶段,而 setImmediate() 会进入紧接着的 check 阶段。
Event Loop 可以简单理解成
timers ↓ pending callbacks ↓ poll ←── I/O 回调通常在这里执行 ↓ check ←── setImmediate() ↓ close callbacks
其中:
- setTimeout(fn, 0) → timers 阶段
- setImmediate(fn) → check 阶段
所以它们不是简单的:
0ms timeout vs 立即执行
实际上 setTimeout(0) 也不是马上执行,而是表示“计时器到期后,尽快在 timers 阶段执行”。
一个非常实用的判断
1. 在普通同步代码里
console.log('A');
setTimeout(() => console.log('B'), 0);
setImmediate(() => console.log('C'));
console.log('D');
一定先:
A D
但 B 和 C 的相对顺序:
A D B C
或者:
A D C B
都可能。
2. 在 I/O 回调里
fs.readFile('test.txt', () => {
setTimeout(() => console.log('timeout'), 0);
setImmediate(() => console.log('immediate'));
});
一般:
immediate timeout
这是实际开发中经常考察的区别。
为什么setImmediate()在 I/O 后更快?
假设当前正在执行:
poll 阶段 ↓ 执行 fs.readFile 的 callback ↓ setImmediate() → check 阶段 ↓ 执行 immediate ↓ 下一轮 ↓ timers 阶段 ↓ 执行 timeout
所以:
setImmediate(...)
相当于:
当前这一轮 Event Loop 的 poll 阶段结束后,尽快执行。
而:
setTimeout(..., 0)
相当于:
至少等待计时器条件满足,然后在 timers 阶段执行。
和浏览器的setTimeout不一样
还有一个容易混淆的地方:
setImmediate 是 Node.js API,不是标准浏览器 API。
Node.js 中:
setTimeout(fn, 0) setImmediate(fn) process.nextTick(fn) Promise.resolve().then(fn)
属于不同的调度机制。
如果你是在准备 Node.js 面试,可以把这几个一起理解:
同步代码 ↓ process.nextTick ↓ Promise microtask ↓ Event Loop ├── timers → setTimeout ├── poll → I/O └── check → setImmediate
不过这里还有一些 nextTick 与 microtask 的细节,以及 Node.js 不同版本 Event Loop 行为差异,面试里很容易被追问。
到此这篇关于Node.js中setImmediate 和 setTimeout(0) 的区别的文章就介绍到这了,更多相关Node.js setImmediate 和 setTimeout(0) 内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
