setTimeout 与 setImmediate 与 process.nextTick 的区别
由 Mux 赞助的 DEV 全球展示挑战赛:展示你的项目!
setTimeout(callback, 0)和有什么区别process.nextTick(callback)?Node 的呢setImmediate(callback)?
表面上看,这三个函数似乎做的是同一件事——它们都在当前事件循环之后、其他任何操作之前执行回调函数。那么自然而然地,为什么会有三个不同的函数呢?让我们做一个实验:
let racer = function() {
setTimeout(() => console.log("timeout"), 0);
setImmediate(() => console.log("immediate"));
process.nextTick(() => console.log("nextTick"));
console.log("current event loop");
}
racer()
从输出结果可以看出,这些回调函数的执行顺序与它们在源代码中编写的顺序并不相同。
[Running] node "/Users/logicmason/timeouts.js"
current event loop
nextTick
timeout
immediate
[Done] exited with code=0 in 0.203 seconds
解释
首先执行的是 `_` process.nextTick,它会将回调函数放在事件队列的前端。它会在当前代码执行完毕后、任何 I/O 事件或定时器之前执行。
接下来是“超时”。由于我们设置的setTimeout超时时间为 0,因此在执行之前不会有额外的强制延迟,它会在下一次循环期间被放入计时器队列中。
最后,我们还有 `setImmediate` setImmediate,它显然不像它的名字那样立即生效!它的回调函数会被放入下一个事件循环的检查队列中。由于检查队列的执行时间晚于定时器队列,因此 `setImmediate` 的执行速度会比 `setTimeout 0` 慢。
总而言之,事件循环如下所示:
timers-> IO-> poll-> check-> close-> timers-> ...
定时器:来自 I/O 事件的回调setInterval;Idle:节点setTimeout
在
I /O 和 Poll 阶段之间内部使用;
Poll:检索新的 I/O 事件;
Check:回调在setImmediate此处执行;
Close:处理已关闭的连接,例如套接字。
挑战时间!
你期望以下Node代码的输出结果是什么?
let racer1 = function() {
setTimeout(() => console.log("timeout"), 0);
setImmediate(() => console.log("immediate"));
process.nextTick(() => console.log("nextTick"));
}
let racer2 = function() {
process.nextTick(() => console.log("nextTick"));
setTimeout(() => console.log("timeout"), 0);
setImmediate(() => console.log("immediate"));
}
let racer3 = function() {
setImmediate(() => console.log("immediate"));
process.nextTick(() => console.log("nextTick"));
setTimeout(() => console.log("timeout"), 0);
}
racer1()
racer2()
racer3()
这是否符合你的预期?
文章来源:https://dev.to/logicmason/settimeout-vs-setimmediate-vs-process-nexttick-3lj2