2

In the official docs, "setImmediate() vs setTimeout()" section, it says: "setImmediate() is designed to execute a script once the current poll phase completes", and as i understand, it means also current tick/event loop cycle.

However later in the "process.nextTick() vs setImmediate()" section, it says: "setImmediate() fires on the following iteration or 'tick' of the event loop".

So which one is the correct answer, did i miss anything here?

Thanks in advance.

Docs relevant page: https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/

Roy
  • 31
  • 1
  • 4
  • [setImmediate executed in check phase] note If scripts have been scheduled by setImmediate() , the event loop will end the poll phase and continue to the check phase to execute those scheduled scripts. that's mean setImmediate will stop the poll phase and not execute code within it and go to check phase to run the script within setImmediate first (that's why setImmediate outside poll phase executed before script within poll phase) – Mahmoud Magdy Jul 04 '22 at 01:50

3 Answers3

2

As you can see by the image below: Event loop Circle

The diagram is from Event Loop and the Big Picture — NodeJS Event Loop Part 1 By Deepal Jayasekara

"The boxes around the circle illustrate the queues of the different phases we seen before, and the two boxes in the middle illustrate two special queues that need to be exhausted before moving from one phase to the other. The “next tick queue” processes callbacks registered via nextTick(), ..."

From Synk - Node.js Event-Loop: How even quick Node.js async functions can block the Event-Loop, starve I/O which reference the article above


So the difference between setTimeout, setImmediate and nextTick is:

  • setTimeout schedules a script to be run after a minimum threshold in ms has elapsed.1
  • setImmediate runs after the poll phase (the pool phase is the IO events queue in the diagram)
  • nextTick runs between phases.

1 The order in which the timers are executed will vary depending on the context in which they are called., see here for more

mihai
  • 4,592
  • 3
  • 29
  • 42
Raz Luvaton
  • 3,166
  • 4
  • 21
  • 36
0

Simple answer:

setImmediate runs on the next tick.

Details:

setImmediate and setTimeout both run in different phases on the event loop.

That is why when setTimeout is set with zero delay it will not run immediately. Use setImmediate which always run on the next tick of the event loop.

but

process.nextTick basically does not care about phases of event loop. The callback you assign to this method will get executed after the current operation is complete and before event loop continues.

The document you linked has a very good explanation about the differences. I'll just grab your attention to few points here. In setimmediate-vs-settimeout the order of call is nondeterministic UNLESS they are scheduled within an I/O cycle like below example.

Now add the process.nextTick to the example

const fs = require('fs');
//  I/O cycle
fs.readFile(__filename, () => {
  setTimeout(() => {
    console.log('timeout');
  }, 0);
  setImmediate(() => {
    console.log('immediate');
  });
});

process.nextTick(() => {
  console.log('nextTick')
})

Output:

nextTick
immediate
timeout

If you run the above code whatever is in process.nextTick function will get executed first. The reason is, it runs before event loop continues. Remember, both setTimeout and setImmediate are event loop related but not process.nextTick.

Be very careful how you use the process.nextTick. You can end up in bad situations if you are not using it properly.

Vahid
  • 1,625
  • 1
  • 18
  • 33
0

The concept of tick is IMO out of scope for us as JS engineers, as there is no native API for us to find or count which tick we are in right now. Sometimes the poll phase waits for the incoming requests to be completed and the event loop stays in the same tick. However, we can indeed try and make sense of the concept with proper code examples.

I asked the same question on the official node.js dev doc and they haven't gotten back to me yet https://github.com/nodejs/nodejs.dev/issues/2343.

Based on the code I ran and observed, the documentation doesn't really explain it clearly. But here it goes:

  • setImmediate runs on the next tick of the event loop in the main module. Eg: The initial code from index.js/main.js.
// Both of the codes will be executed in the next tick of the event loop.
// Depending on the event-loop start time, if the timer is executed in the next tick, then setImmediate will also do the same, as the check-phase follows the timers phase.
// If the timer is delayed further then only setImmediate will be executed in the next tick and the timer a tick after that.

setTimeout(() => console.log('May be I run first'), 0);
setImmediate(() => console.log('May be I run first'));
 
 
  • setImmediate runs on the same iteration of the event loop inside an I/O callback. Because timer callbacks are always executed after setImmediate callbacks.
  fs.read('/file/path', () => {

    // check phase follows the I/O phase and poll phase. 
    // And when the poll phase is idle then the check phase is run right after.
    setImmediate(() => console.log('I am printed first always'));

    // Timers will be deferred to the next tick as timers-phase are the start of a "tick".
    setTimeout(() => console.log('I will be called in the next tick'), 0);
   
    setTimeout(() => console.log('I will be called may be tick after next one'), 100);
    

  });