You are currently viewing Asynchronous Programming in Node.js

Asynchronous Programming in Node.js

What is asynchronous programming?

In order to define asynchronous programming we need to understand what is synchronous programming.

In synchronous programming, code is executed line by line in a sequence. So if a line of code is calling a method that took a long time to execute, the flow will be stuck there until the response comes back from that particular method, thus next line of codes will be executed once the response comes back from the previous method.

On the other hand, asynchronous programming is the opposite of synchronous programming. In asynchronous programming code is executed concurrently and independent of each other. So in contrast to synchronous programming, if a code or method is taking a long to complete, the next line of code will still be executed without waiting for the previous task to complete.

Example 1

Let’s start with a very simple and basic example to clearly understand the difference between synchronous and asynchronous programming. 

console.log("Hello World!")
console.log("Hello Universe!")

If we execute the above two lines, we will see the following out put on our terminal window.

Hello World!
Hello Universe!

The above output is obvious, as it executes two lines in sequence and is an example of synchronous programming.

Now let’s modify the above code and induct some asynchronous code in it. The modified code is given below:-

setTimeout(()=>{console.log("Hello World!")}, 3000) 
console.log("Hello Universe!")

Before seeing the output of the above code, let’s discuss the “setTimeout” function which I’ve used in this code.

The “setTimeout” method is asynchronous in Node.js. This method accepts a method to execute and it also accepts the time (in milliseconds) for the delay. The first method which it accepts is called the call-back method. i.e. Once the time is mentioned in the second parameter (i.e. delay parameters), the callback method will be executed. 

So our first line of code is stating to execute the method (anonymous) after 3000 milliseconds (i.e. After three seconds). Since this is an asynchronous method, our next line of code should not be waiting for 3 seconds to print “Hello Universe!”

So if all above is true, then the output should be showing “Hello Universe!” as the first out put, and after ~ 3 seconds it should be showing “Hello World!” 

In the above video, it can be seen that “Hello Universe!” appears before appearing “Hello World!”

Example 2

In the second example, Instead of using the built-in asynchronous method, I will write my asynchronous method. There are some basic rules to write and use the asynchronous methods in programming and those are given below:-

  • Define the method as asynchronous. In Node.js and even in C# the keyword to declare the asynchronous is “async”
  • When invoking the asynchronous method, it is recommended to use the await keyword both in Node.js. 
When you call an asynchronous method, it returns a promise in Node.js. The await keyword makes sure that the promise returned by the async method is resolved. 

In the following, I have written a method that accepts a number and calculates its factorial.

async function factorial(number) {
  if (number === 0) {
    return 1;
  } else {
    const result = await factorial(number - 1);
    return number * result;
  }
}

In the above code, we can see that this method named “factorial” is just like a normal method except with the difference that it used the “async” keyword. Adding this keyword makes this method an asynchronous method.

Now let’s invoke this method in our program. The code to call this method is given below, and please note that I deliberately made a mistake in order to call this method and did not use the await keyword.

const res= factorial(5)
console.log(res)

Now compiling the code given me the following result

PS F:\Hands on Tutorial\Node.js\DeleteMe> node index.js
Promise { <pending> }

The above result clears our understanding that the async method returns the “promise”. So in order to get the response from this async method, we have two options which I stated previously and these two options are given below:-

  • keyword “then”
  • keyword “await”

We use the keyword “then” when we are inside a method that is not async. The usage of “then” keyword is given as below:-

Using the "then" keyword

factorial(5).then((result)=>
  {
    console.log(result)
  })

console.log("After the Factorial call")

In the above code, we are calling the method just like we called it previously with the difference that this time we also used the keyword “then”. This keyword makes sure to execute the callback method when the promise is completed. which in this case is an anonymous method as the first argument of the “then”.

Now let’s run this code and see what is produces for us. The output of the above code is given below:-

Output

PS F:\Hands on Tutorial\Node.js\DeleteMe> node index.js
After the Factorial call
120

In the above output, we can observe the followings:-

  • “After the Factorial call” appears before the result of the factorial result. It happens due to the fact that our factorial method is an async method (i.e. nonblocking code), thus the line next to the method invoking call executed immediately. It did not wait for the result of the factorial’s result.
  • Once the promise is completed, the callback method which is pointed by the “then” method executed itself. 
  • The “then” method is an instance of promise, and it takes two arguments. 
  • The “then” method also returns a promise allowing us to make a complex chain of call backs.

using the "await" keyword

The other way to invoke the async method is the use of the “await” keyword. This keyword provides better code readability. As mentioned earlier “await” can only be used inside the async method. To double-check, let’s call the factorial method using the await keyword without wrapping it inside the async method.

let response = await factorial(5)

Compiling the above code will give us a compile time error which is given below:-

let response = await factorial(5)
               ^^^^^

SyntaxError: await is only valid in async functions and the top level bodies of modules

The “await” keyword await for the promise to be settled and then it gives the response. It basically pauses the execution of the wrapper async method until the promise is resolved. So if its wrapping method is not async, the code will not make sense. That is why in programming languages including in C#, await keyword can only be used inside the async method.

To make life easier for the developer, the compiler throws the error if await is not inside the async method. So in order to get rid of this compile time error, I have modified the code and the updated code is given below:-

const result = async (n) => {
  const factResult = await factorial(n);
  console.log(`The factorial of ${n} is , ${factResult}`)
};

In order to invoke the above async method, just use it the way we normally invoke the normal method. 

result(10);

Output

The factorial of 10 is , 3628800

Complete Code


async function factorial(number) {
  if (number === 0) {
    return 1;
  } else {
    const result = await factorial(number - 1);
    return number * result;
  }
}
const result = async (n) => {
  const factResult = await factorial(n);
  console.log(`The factorial of ${n} is , ${factResult}`)
};
factorial(5).then((result)=>
  {
    console.log(result)
  })
console.log("After the Factorial call")
result(10);
console.log("Hello World!")

Complete Output

After the Factorial call
Hello World!
120
The factorial of 10 is , 3628800

Use cases of Async Code

There are several use cases of using async programming. It really comes in handy when you have a code block that took a long time to execute and in normal sync programs, it will pause the execution of the next lines of code to execute. So, we need to use it in all such cases where some code block took a long time to complete. Some of the scenarios are given below:-

  1. Processing large amounts of data
  2. Making requests over the network
  3. Communication with Database
  4. Real-time applications
  5. Developing non-blocking user interfaces

Leave a Reply