Node.js Ultimate Guide for Beginner — Part 2

Series - Node.js Ultimate Guide for Beginner

Before continuing, make sure to check the previous part here Node.js Ultimate Guide for Beginner – Part 1

You may want to read this article in Bahasa Indonesia version: Node.js Ultimate Guide untuk Pemula — Part 2

In this part, we will learn how Node.js works, especially regarding the concepts of callbacks, Promise, and async and await in JavaScript and how to implement them in Node.js.

Node.js System Flow

Node.js is often referred to as a JavaScript runtime that operates asynchronously in an event-driven manner. Asynchronous programming is one of the important concepts in JavaScript that allows us to run multiple tasks simultaneously without having to wait for previous tasks to complete.

Explanation about Node.js in their official documentation (Source: https://nodejs.org/en/about)
Explanation about Node.js in their official documentation (Source: https://nodejs.org/en/about)

So unlike other runtimes that operate in a blocking manner, meaning every execution of the program code must wait until other codes are completed. Node.js, on the other hand, has most of its APIs designed to be non-blocking, allowing codes to run simultaneously without having to wait for previous codes to finish. For further explanation about blocking and non-blocking, you can read it here.

Visually, here’s how Node.js works:

Node.js system flow (Source: https://medium.com/@alexchristianqr/arquitectura-de-node-js-conceptos-importantes-de-nivel-senior-f1a5a6d478fd)
Node.js system flow (Source: https://medium.com/@alexchristianqr/arquitectura-de-node-js-conceptos-importantes-de-nivel-senior-f1a5a6d478fd)

In the image, each API has its own worker thread. Each worker thread works simultaneously when there is a request coming in from the event loop. This is where the event loop plays a vital role: it handles each incoming request in the event queue, places it in the appropriate worker thread, and returns the processing results to the correct event queue.

If the explanation above is too hard to understand, we can start by first understanding the concepts of events and callbacks in Node.js.

Events and Callbacks

First, let’s start with callbacks. A callback is a function that is passed as an argument to another function and will be executed after that function completes. This is where the power of asynchronous comes in: we can run other codes while waiting for the asynchronous process to finish.

However, there is a downside to callbacks, known as callback hell. When we start calling many nested callbacks, the code becomes difficult to read and maintain. Here’s a simple example of a callback in JavaScript:

javascript

function sayHello(callback) {
  console.log('Hello');
  callback();
}

sayHello(function() {
  console.log('World!');
});

However, as mentioned, the more callbacks we register, the messier the code becomes.

Promise

To address this issue, Promise emerged. A Promise helps us handle asynchronous operations more neatly and cleanly. In a Promise, we can do something after the promise is either resolved (successful) or rejected (failed).

For example, here’s how to use a Promise:

javascript

const promise = new Promise(function(resolve, reject) {
  const success = true;

  if (!success) {
    return reject('Failure!');
  }
  
  return resolve('Success!');
});

promise.then(function(result) {
  console.log(result); // Success!
}).catch(function(error) {
  console.log(error); // Failure!
});

With a Promise, we can avoid callback hell because we can use the .then() method to capture the result of the promise when it is successful, and .catch() to capture any errors that occur.

However, there’s one thing to keep in mind: if we only return a Promise without handling its result, we will only get a Promise object without the desired result. To see the result, we need to call then as shown in the example above.

Async/Await

Now, async and await are improvements over Promise that make asynchronous code much easier to read. With async/await, we no longer need to create many .then() methods to handle the results of a Promise. Instead, we simply add the await keyword in front of the Promise we call, and the result will be directly stored in a variable.

Here’s an example of using async/await:

javascript

async function fetchData() {
  const response = await fetch('https://api.example.com/data');
  const data = await response.json();
  
  console.log(data);
}

fetchData();

What happens here? By using await, we make the code seem to “wait” for the result of the fetch API before continuing to the next line. But don’t worry, even though it looks like synchronous, it is still asynchronous behind the scenes. Therefore, we always need to wrap the code that uses await in a function prefixed with the async keyword.

And one thing to remember, an async function will always return a Promise. This means that even if we do not explicitly write return new Promise(), the function automatically produces a Promise.

Implementation in Node.js

Let’s take a simple example of how to use async/await in a Node.js project.

javascript

async function main() {
  try {
    const response = await fetch('https://api.example.com/data');
    const data = await response.json();
    
    console.log(data);
  } catch (error) {
    console.error('Error fetching data:', error);
  }
}

main();

In the code above, we wrap fetch and response.json() with await, so we no longer need to use .then() again. This makes the code cleaner and easier to understand.

Penutup

So, that’s a brief overview of asynchronous in JavaScript. Starting from callbacks, Promise, to async/await, all of them play their respective roles in making asynchronous code more efficient and easier to read. If you are just starting to learn, understand the basic concepts first, and don’t worry if it feels complicated at first. With practice, you will surely get used to it and understand more.

In the next part, we will try to learn how to create a Node.js project with npm init, push it to GitHub, and then deploy it to Render. If there are any other Node.js topics you want us to discuss together, feel free to share your thoughts in the comments! Thank you.


Source

Related Content