发布于 2026-01-06 1 阅读
0

setTimeout vs setImmediate vs process.nextTick DEV 的全球展示挑战赛,由 Mux 呈现:展示你的项目!

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 事件的回调setIntervalIdle:节点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()

这是否符合你的预期?

订阅logicmason.com获取更多内容

文章来源:https://dev.to/logicmason/settimeout-vs-setimmediate-vs-process-nexttick-3lj2