Gabriel Llamas Gabriel Llamas - 4 months ago 37
Node.js Question

nextTick vs setImmediate, visual explanation

I'm very confused about the differences between nextTick and setImmediate. I've read all the documentation about them on the internet but I still don't understand how they work.

Examples:

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


Why these results? Please explain with a visual or very easy to follow explanation. Even the node core devs don't agree at how nextTick and setImmediate should be understood by people.

Sources:


Answer

Consider the following two examples:

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 callbacks are fired off the event loop, once per iteration in the order that they were queued. So on the first iteration of the event loop, callback A is fired. Then on the second iteration of the event loop, callback B is fired, then on the third iteration of the event loop callback C is fired, etc. This prevents the event loop from being blocked and allows other I/O or timer callbacks to be called in the mean time (as is the case of the 0ms timeout, which is fired on the 1st or 2nd loop iteration).

nextTick callbacks, however, are always fired immediately after the current code is done executing and BEFORE going back to the event loop. In the nextTick example, we end up executing all the nextTick callbacks before ever returning to the event loop. Since setTimeout's callback will be called from the event loop, the text 'TIMEOUT FIRED' will not be output until we're done with every nextTick callback.