Unlocking Asynchronous Power with Node.js and Libuv

AkritiAkriti
4 min read

Synchronous Vs Asynchronous System

  • Synchronous System: In a synchronous system, tasks execute sequentially, potentially blocking the main flow.
console.log("synchronous");
let a = 10;
let b = 20;
function add(x,y){
    const res = (a + b);
    return res;
}
let c = add(a,b);
//these tasks can execute immediately
  • Asynchronous System: In an asynchronous system, tasks operate independently, ensuring smoother and faster execution without blocking the main flow.
console.log("asynchronous");
fs.readFile("./doc.txt" , "utf8" , (data) => {
    console.log("File Data" , data);
}
setTimeout(() => {
    console.log("Wait for 5 sec");
}, 5000); 
//these task take time to execute
//output:
// asynchronous
//Wait for 5 sec
//File Data {data}

So, JavaScript, by default, operates synchronously. However, when paired with Node.js, it gains the ability to handle asynchronous tasks concurrently. This empowers JavaScript to perform multiple operations independently.
Hence JavaScript is an asynchronous and synchronous both.

Let’s see the execution of:

Synchronous System

  • When JavaScript code starts running, it creates a Global Execution Context the primary environment for executing top-level code. This context is unique and always takes the lead on the call stack.

  • In the memory creation phase, JavaScript sets aside space for variables (like a and b) and stores the function (add) with its entire definition. Variables start as ‘undefined,’ awaiting their purpose.

  • In the code execution phase:

    1. Variables a and b receive their assigned values.

    2. The function add(a, b) is invoked, creating a dedicated execution context for it.

  • When add(a, b) is invoked, a fresh execution context for add is created and added to the call stack. Inside this context, the parameters x and y receive the values of a and b, respectively.

  • Within add, memory initializes res as undefined. Then, the multiplication (const res = a + b;) yields the value 30. Finally, the function returns this result, and its execution context gracefully exits the call stack.
  • Returning from the add adventure, the value 30 now graces the variable c in the global execution context.
  • As our code performance reaches its final curtain, the global execution context exits, and the call-stack become empty.

Asynchronous System

  • Asynchronous system includes fetching data from a server, reading files, or handling user input. Instead of blocking everything until a task completes JavaScript lets other tasks run while waiting for slowpokes.

  • Now, let’s introduce Node.js.Node.js is the superhero sidekick to our JavaScript engine. It equips the engine with superpowers. Here’s how it works:

    1. JS Engine: JavaScript engine can’t do everything alone. It’s great at cooking up code, but it can’t directly access the operating system (OS) or perform file operations.

    2. Node.js: Wearing a cape made of C++ code. Node.js bridges the gap between JavaScript and the OS.

    3. Libuv: Node.js owes its powers to a magical library called Libuv. Think of Libuv as the secret ingredient—the spice that makes everything work smoothly. Libuv communicates with the OS, juggles tasks, and keeps the code running.

Role of Libuv:

  1. Task Delegation: When JS engine needs to read a file or make an HTTP request, it calls on Libuv. “Hey, Libuv, fetch this file for me!” Libuv nods and gets to work.

  2. Non-Blocking Goodness: Libuv doesn’t block the js engine. While it talks to the OS, the js engine can keep executing. No waiting around! Libuv handles file I/O, timers, and network requests, all without pausing the main script.

  3. Callbacks and Events: Libuv uses callbacks and events. When the file is ready, it taps the engine on the shoulder: “Your file is ready”!

  4. Behind the Scenes: Libuv performs its magic backstage. It manages event loops, handles concurrency, and ensures our application runs smoothly.

Therefore, the program starts by logging “asynchronous” to the console.

  • While the file reading operation is in progress (asynchronous), the rest of the code continues executing.

  • After 5 seconds, the scheduled timeout callback runs and logs “Wait for 5 sec” to the console.

  • Eventually, when the file reading completes, the callback function logs the file data.

10
Subscribe to my newsletter

Read articles from Akriti directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Akriti
Akriti

“Innovative developer with a passion for continuous learning and expertise in cutting-edge technologies. Proficient in frontend development, particularly ReactJS and Tailwind CSS, and currently expanding my skills in Node.js and backend development. Enthusiastic about creating seamless user experiences and optimizing performance. Always eager to explore new tools and frameworks to stay ahead in the tech world.”