Shams Nahid
Shams Nahid's Blog

Shams Nahid's Blog

Node.js Internals: Lifecycle of the Event Loop

Node.js Internals: Lifecycle of the Event Loop

Explanation of how Node.js Event Loop works

Shams Nahid's photo
Shams Nahid
·Sep 10, 2022·

3 min read

Table of contents

  • Lifecycle
  • Tick
  • Summary

Node.js is used for building highly scalable server-side applications using JavaScript. It provides,

  • Event-driven
  • Non-blocking (asynchronous) I/O
  • cross-platform runtime environment

The event loop is the core player for maintaining these properties and makes Node.js a faster runtime.

Lifecycle

Anytime we run a node.js program, it creates one thread and then runs all of our codes inside that thread.

The event loop acts as a control structure to decide, what our one thread should be doing at one given time.

When we run a js file, Node first takes all the codes and executes them. This is the moment we enter the event loop.

Every time the event loop executes a cycle, in the Node.js world, it is called tick.

Every time the event loop is about to execute, Node quickly checks whether the loop should proceed or not for another iteration. If node decides not to run more iteration, the program closes and we go back to the terminal.

The event loop continues to the next iteration when shouldContinue method returns true.

When node first goes through the code first time, it detects pendingTimers, pendingOSTasks, and pendingOperations.

Tick

Every single iteration of an event loop is called a tick. In pseudo-code, it looks as follows

// javascript code is written inside the myFile.js

const pendingTimers = [];
const pendingOSTasks = [];
const pendingOperations = [];

// New timers, tasks, operations are recorded from myFile
myFile.runContents();

function shouldContinue() {
  // Check one: Any pending setTimeout, setInterval, setImmediate?
  // Check two: Any pending OS tasks? (Like server listening to port, network calls)
  // Check three: Any pending long running operation? (Like fs module, thread pools tasks)
  return (
    pendingTimers.length || pendingOSTasks.length || pendingOperations.length
  );
}

// Entire body executes in one 'tick'
while (shouldContinue()) {
  // 1) Node looks at pending timers and sees if any functions are ready to be called (setTimeout, setInterval)
  // 2) Node looks at pendingOSTasks and pendingOperations and calls relevant callbacks
  // 3) Node pause the execution until,
  //   - a pendingOSTasks is done
  //   - a pendingOperation is done
  //   - a timer is about to complete
  // 4) Look at pendingTimers. Call any setImmediate (This time node does not care about setTimeout or setInterval, it only looks at those functions, registered with setImmediate)
  // 5) Handle any 'close' events
}

Summary

In summary, the Node.js event loop,

  1. Process and execute code in index.js
  2. Look for pending timers, OS tasks, pending operations. If no tasks exist, exit.
  3. Run setTimeout's, setInterval's
  4. Run callbacks for OS tasks and thread pools pending stuff
  5. Pause and wait for stuff done
  6. Run setImmediate functions
  7. Handle close events
  8. Return to step 2

References: Node JS: Advanced Concepts By Stephen Grider

 
Share this