vivek
vivek

Reputation: 1

Understanding Node.Js Event Loop Execution

I am new to node.js and trying to understand the event loop. As we know, process.nextTick() is not a part of Event Loop. So, can anyone also explain if process.nextTick() callback will execute before event loop starts? Please include different node.js event loop phase state in your explanation.


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

    console.log("close")

    setTimeout(() => {
        console.log("1")
        console.log('timeout');
      }, 0);

      setImmediate(() => {
        console.log("2")
        console.log('immediate');
      });

Upvotes: 0

Views: 634

Answers (1)

palo
palo

Reputation: 51

Let me try

You can find brief (16 minutes) explanation about the node's event loop here:
https://www.youtube.com/watch?v=PNa9OMajw9w&list=PLw5h0DiJ-9PCIrjcodoAZdA4CcCarnCOo&index=2

The official guide (mentioned by @estus) is the best explanation:
https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/

For more in depth explanation, check this series of blogposts:
https://jsblog.insiderattack.net/event-loop-and-the-big-picture-nodejs-event-loop-part-1-1cb67a182810

According the official guide:

You may have noticed that process.nextTick() was not displayed in the diagram, even though it's a part of the asynchronous API. This is because process.nextTick() is not technically part of the event loop. Instead, the nextTickQueue will be processed after the current operation is completed, regardless of the current phase of the event loop.
Looking back at our diagram, any time you call process.nextTick() in a given phase, all callbacks passed to process.nextTick() will be resolved before the event loop continues.

So, the process.nextTick() callbacks will be executed each event loop's tick, not before the event loop starts.
Let me demonstrate with this simple program:

 process.nextTick(() => console.log("process.nextTick before"));
 const intervalId = setInterval(() => {
   console.log("interval");
   process.nextTick(() => console.log("process.nextTick from interval"));
 }, 1000);
 process.nextTick(() => console.log("process.nextTick after"));

 setTimeout(() => {
   clearInterval(intervalId);
   console.log("Interval was cleared - nothing more to run - the event loop will stop - program will stop");
 }, 5000);

This is the output:

process.nextTick before
process.nextTick after
interval
process.nextTick from interval
interval
process.nextTick from interval
interval
process.nextTick from interval
interval
process.nextTick from interval
Interval was cleared - nothing more to run - the event loop will stop - program will stop

Explanation:

  • process.nextTick(() => console.log("process.nextTick from interval")); puts a callback into the nextTickQueue (also called the microtasks queue). Therefore the text 'process.nextTick from interval' is printed after the first text 'interval', but before the next text 'interval'. All callbacks from the microtasks queue will run before the event loop continues to the next phase (see the aforementioned quote from the official guide).
  • texts 'process.nextTick before' and 'process.nextTick after' were printed before the first interval text, because the nextTickQueue was processed before the event loop started. From the official guide:

    When Node.js starts, it initializes the event loop, processes the provided input script (or drops into the REPL, which is not covered in this document) which may make async API calls, schedule timers, or call process.nextTick(), then begins processing the event loop.

Back to your example.

This is the output of your program:

close
3
nextTick
1
timeout
2
immediate

Explanation:

  1. text: 'close' - printed first - because node has processed the input script
  2. texts: '3' ; 'nextTick' - printed second - because the callbacks from the nextTickQueue were run before the event loop started
  3. texts: '1' ; 'timeout' - printed third - because callbacks scheduled by setTimeout or setInterval are run during the timer phase - the first phase
  4. texts: '2' ; 'immediate' - printed fourth - because callbacks scheduled by 'setImmediate' are run during the check phase - the fifth phase

Hopefully this long answer makes things clear.

Upvotes: 2

Related Questions