Node.js events and event loop

Node.js is a powerful JavaScript runtime built on Chrome's V8 engine. One of its standout features is the event-driven, non-blocking I/O model, which makes it ideal for building scalable network applications. Understanding how Node.js handles events and the event loop is crucial for mastering this platform. This chapter delves into these concepts, providing a comprehensive guide from basic principles to advanced techniques.

What are Events?

In Node.js, events are signals that indicate something has happened in the application. These signals can be triggered by various sources, such as user actions, network requests, timers, or even other parts of the code.

The EventEmitter Class

The EventEmitter class is the heart of the event system in Node.js. It allows objects to emit events and listen for them. Here’s a basic example:

				
					const EventEmitter = require('events');
const myEmitter = new EventEmitter();

myEmitter.on('event', () => {
  console.log('An event occurred!');
});

myEmitter.emit('event');

				
			

Explanation:

  • require('events'): Imports the events module.
  • EventEmitter: The class that handles events.
  • myEmitter.on('event', callback): Registers a listener for the ‘event’.
  • myEmitter.emit('event'): Triggers the ‘event’.
				
					// Output //
An event occurred!

				
			

Creating Custom Events

You can create custom events by extending the EventEmitter class.

Custom Event Example

				
					const EventEmitter = require('events');

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();

myEmitter.on('customEvent', (message) => {
  console.log(`Custom event received: ${message}`);
});

myEmitter.emit('customEvent', 'Hello, world!');

				
			

Explanation:

  • class MyEmitter extends EventEmitter: Creates a new class that inherits from EventEmitter.
  • myEmitter.on('customEvent', callback): Registers a listener for the ‘customEvent’.
  • myEmitter.emit('customEvent', 'Hello, world!'): Triggers the ‘customEvent’ with a message.
				
					// Output //
Custom event received: Hello, world!

				
			

The Event Loop

The event loop is a fundamental concept in Node.js. It’s a loop that continuously checks the event queue and processes any events or callbacks that are waiting to be executed.

How the Event Loop Works

  1. Timers: Checks if any timers (setTimeout, setInterval) are ready to be executed.
  2. Pending Callbacks: Executes I/O callbacks deferred to the next loop iteration.
  3. Idle, Prepare: Internal use only.
  4. Poll: Retrieves new I/O events; executes I/O-related callbacks.
  5. Check: Executes setImmediate() callbacks.
  6. Close Callbacks: Executes close event callbacks (e.g., socket.on(‘close’, …)).

Timers

Timers in Node.js are functions that execute after a certain period. The two most commonly used timers are setTimeout and setInterval.

setTimeout

				
					setTimeout(() => {
  console.log('This executes after 2 seconds');
}, 2000);

				
			

Explanation:

setTimeout(callback, delay): Schedules the callback to execute after delay milliseconds.

				
					// Output (after 2 seconds):
This executes after 2 seconds

				
			

setInterval

				
					let counter = 0;
const interval = setInterval(() => {
  counter += 1;
  console.log(`Interval count: ${counter}`);
  if (counter === 5) {
    clearInterval(interval);
  }
}, 1000);

				
			

Explanation:

  • setInterval(callback, delay): Repeatedly executes the callback every delay milliseconds.
  • clearInterval(interval): Stops the interval when the condition is met.d
				
					// Output (after 2 seconds):
Interval count: 1
Interval count: 2
Interval count: 3
Interval count: 4
Interval count: 5

				
			

setImmediate and process.nextTick

Both setImmediate and process.nextTick are used to schedule callbacks, but they have different use cases.

setImmediate

				
					setImmediate(() => {
  console.log('This executes after the current event loop cycle');
});
console.log('This executes before setImmediate');

				
			

Explanation:

  • setImmediate(callback): Schedules the callback to execute after the current event loop cycle.
				
					// Output //
This executes before setImmediate
This executes after the current event loop cycle

				
			

process.nextTick

				
					process.nextTick(() => {
  console.log('This executes after the current operation, before the next event loop');
});
console.log('This executes before process.nextTick');

				
			

Explanation:

  • process.nextTick(callback): Schedules the callback to execute after the current operation, before the next event loop.
				
					// Output //
This executes before process.nextTick
This executes after the current operation, before the next event loop

				
			

Asynchronous I/O

Node.js excels at handling asynchronous I/O operations, which are crucial for non-blocking performance.

Asynchronous File Read

				
					const fs = require('fs');

fs.readFile('example.txt', 'utf8', (err, data) => {
  if (err) throw err;
  console.log(data);
});
console.log('Reading file...');

				
			

Explanation:

  • fs.readFile(file, encoding, callback): Asynchronously reads the contents of the file and executes the callback with the result.
  • The callback handles the file content once it is read, while the rest of the code continues executing.
				
					// Output //
Reading file...
(File content of example.txt)

				
			

Real-World Example: HTTP Server

A common use case for Node.js is creating an HTTP server.

Basic HTTP Server

				
					const http = require('http');

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello, World!\n');
});

server.on('request', (req, res) => {
  console.log(`Request received for: ${req.url}`);
});

server.listen(3000, '127.0.0.1', () => {
  console.log('Server running at http://127.0.0.1:3000/');
});

				
			

Explanation:

  • http.createServer(callback): Creates an HTTP server that executes the callback for each request.
  • server.on('request', callback): Registers a listener for the ‘request’ event.
  • server.listen(port, hostname, callback): Starts the server and executes the callback when it is ready.
				
					// Output //
Server running at http://127.0.0.1:3000/
(Request received for: /)
Hello, World!

				
			

Summary

  • Events: Signals indicating something has happened.
  • EventEmitter: Core class for handling events.
  • Event Loop: Continuously checks the event queue and processes events.
  • Timers: setTimeout and setInterval for delayed execution.
  • setImmediate & process.nextTick: Scheduling callbacks.
  • Asynchronous I/O: Non-blocking operations for performance.
  • HTTP Server: Practical example of Node.js in action.

Understanding Node.js events and the event loop is crucial for leveraging the full potential of this powerful runtime. The non-blocking, event-driven architecture enables the development of high-performance, scalable applications. By mastering concepts like EventEmitter, timers, setImmediate, process.nextTick, and asynchronous I/O, you can build robust Node.js applications that handle concurrent operations efficiently.Happy coding !❤️

Table of Contents

Contact here

Copyright © 2025 Diginode

Made with ❤️ in India