一尘不染

nextTick vs set立即,直观的说明

node.js

我对nextTick和setImmediate之间的区别感到非常困惑。我已经在互联网上阅读了有关它们的所有文档,但我仍然不明白它们是如何工作的。

例子:

function log(n) { console.log(n); }

setImmediate

setImmediate(function() {
  setImmediate(function() {
    log(1);
    setImmediate(function() { log(2); });
    setImmediate(function() { log(3); });
  });
  setImmediate(function() {
    log(4);
    setImmediate(function() { log(5); });
    setImmediate(function() { log(6); });
  });
});

//1 2 3 4 5 6

nextTick

process.nextTick(function() {
  process.nextTick(function() {
    log(1);
    process.nextTick(function() { log(2); });
    process.nextTick(function() { log(3); });
  });
  process.nextTick(function() {
    log(4);
    process.nextTick(function() { log(5); });
    process.nextTick(function() { log(6); });
  });
});

//1 4 2 3 5 6

为什么会有这些结果?请以视觉或非常容易理解的方式进行说明。甚至节点核心开发人员也不同意人们应该如何理解nextTick和setImmediate。

资料来源:


阅读 286

收藏
2020-07-07

共1个答案

一尘不染

考虑以下两个示例:

setImmediate

setImmediate(function A() {
  setImmediate(function B() {
    log(1);
    setImmediate(function D() { log(2); });
    setImmediate(function E() { log(3); });
  });
  setImmediate(function C() {
    log(4);
    setImmediate(function F() { log(5); });
    setImmediate(function G() { log(6); });
  });
});

setTimeout(function timeout() {
  console.log('TIMEOUT FIRED');
}, 0)

// 'TIMEOUT FIRED' 1 4 2 3 5 6
// OR
// 1 'TIMEOUT FIRED' 4 2 3 5 6

nextTick

process.nextTick(function A() {
  process.nextTick(function B() {
    log(1);
    process.nextTick(function D() { log(2); });
    process.nextTick(function E() { log(3); });
  });
  process.nextTick(function C() {
    log(4);
    process.nextTick(function F() { log(5); });
    process.nextTick(function G() { log(6); });
  });
});

setTimeout(function timeout() {
  console.log('TIMEOUT FIRED');
}, 0)

// 1 4 2 3 5 6 'TIMEOUT FIRED'

setImmediate回调从事件循环中触发,每次迭代按排队的顺序进行一次。因此,在事件循环的第一次迭代中,将触发回调A。然后,在事件循环的第二次迭代中,将触发回调B,然后在事件循环的第三次迭代中,将触发回调C,以此类推。这样可以防止事件循环被阻塞,并允许其他I
/ O或计时器回调在平均时间中调用(与0ms超时的情况相同,它在第1次或第2次循环迭代中触发)。

但是,总是在执行完当前代码之后并返回事件循环之前立即触发nextTick回调。在nextTick示例中,在返回事件循环之前,我们最终执行了所有nextTick回调。由于将从事件循环中调用setTimeout的回调,因此直到完成每个nextTick回调后,才会输出文本“
TIMEOUT FIRED”。

2020-07-07