Skip to main content

Command Palette

Search for a command to run...

How NodeJS Works?

Understanding the Event-Driven Architecture of Node.js

Updated
3 min read
How NodeJS Works?
T

I am an independent full-stack developer with experience in the MERN stack and currently a student pursuing a B.Tech degree in Computer Science and Engineering. I am passionate about building my version of the digital world, one coding project at a time, with a focus on planning, design, and solving real-life problems with code. I am open to any new opportunities that may arise.

Introduction:

Node.js is a powerful runtime environment that utilizes an event-driven, non-blocking I/O model to build scalable and efficient applications. In this article, we will delve into how Node.js works, exploring its event-driven architecture, event queue, event loop, and the handling of blocking and non-blocking events.

Event Queue and Event Loop

When a client sends a request to a Node.js server, the request enters the event queue. The event loop, a key component of Node.js, continuously monitors the event queue for incoming events. It follows a first-come, first-served approach, ensuring that events are processed in the order they were received.

Non-Blocking and Blocking Events

Node.js distinguishes between non-blocking and blocking events. Non-blocking events can be executed asynchronously without blocking the execution of subsequent code. On the other hand, blocking events require additional resources and may cause delays. Node.js efficiently handles both types of events.

Non-Blocking Event Execution

For non-blocking events, Node.js executes them in an event-driven manner. The event loop constantly checks for completed non-blocking events, and once an event is finished, its corresponding callback function is triggered, and the output is returned.

Blocking Event Handling

When a blocking event is encountered, Node.js offloads the operation to a thread from the thread pool, also known as a worker. The worker is responsible for executing the blocking operation. If all workers are occupied, the event has to wait until a worker becomes available. This approach prevents blocking events from causing delays or blocking the execution of subsequent events.

Optimizing Node.js Performance:

To optimize Node.js performance, it is crucial to minimize the number of blocking events and prioritize non-blocking operations. By leveraging asynchronous programming techniques and utilizing non-blocking I/O operations, developers can ensure that Node.js applications are highly scalable and responsive.

In a real-life scenario, consider a web application that needs to fetch data from an external API and display it on a webpage. Using a blocking approach, the code would pause the execution until the response is received, resulting in a frozen browser and unresponsive webpage. On the other hand, a non-blocking approach allows the code to continue execution while waiting for the response, keeping the browser responsive and enabling the user to interact with the webpage. This enhances the user experience and ensures uninterrupted interaction with the application.

Example

When working with the fs module in Node.js, it's important to understand the difference between fs.readFileSync and fs.readFile in terms of their blocking and non-blocking behavior.

Note: Content of created.txt : Created file using writeFile

When using readFileSync :

const fs = require("fs");

console.log(1);
console.log(2);

//readFileSync is blocking, it blocks the execution of code until
//and unless it is completed
const res = fs.readFileSync("./created.txt", "utf-8");
console.log(res);

console.log(3);
console.log(4);

When using readFile :

const fs = require("fs");

console.log(1);
console.log(2);

//readFile is non blocking, that it dosent block instead run
//asynchronously
fs.readFile("./created.txt", "utf-8", (err, response) => {
  if (err) console.log(err);
  else {
    console.log(response);
  }
});

console.log(3);
console.log(4);

  • fs.readFileSync is a non-blocking function that reads file contents synchronously. It blocks the execution of subsequent code until the file reading operation completes. This can impact performance and responsiveness, especially in scenarios with concurrent requests.

  • fs.readFile is a blocking function that reads file contents asynchronously. It expects a callback function and schedules the file reading operation, allowing subsequent code to execute without blocking. Once the operation finishes, the callback is invoked with the file contents or any potential errors.

In summary, fs.readFileSync is non-blocking and fs.readFile is blocking because it expects a callback function and works asynchronously, respectively. It's important to consider the potential impact on performance and responsiveness when choosing between these methods based on your application's requirements.


Thanks a lot for reading the article.
Hope you found it helpful.

Linkedin: https://www.linkedin.com/in/tautikk/
Email: tautikagrahari@gmail.com
Twitter: https://twitter.com/TautikA

H

Nice Example and explaination. Next, Can you write the blog about when to to you which functionality from Blocking and non-blocking.

1
T

Thanks for the feedback. Updated in Optimizing Node.js Performance section, provided an real life example you could relate to.

N

This is a very nice blog Tautik Agrahari even I am learning nodejs MongoDB, express and documenting my journey here on hashnode. Will love to connect!

1
T

sure, its nice to meet you lets share knowledge and learn from each other :)

N

@nikktwts is my twitter profile lets connect

1
H

Very informative.

1
T

Thanks a lot for the feedback, I had added an example right now for better understanding :)