Advanced Techniques for Asynchronous Programming in JavaScript

If we talk about traditional or synchronous programming, then every person will have to wait for another person to let them complete his task, so after that, they can start their task.

But with asynchronous programming, every person can start their work simultaneously without waiting for each other to complete it. If you are looking for the best SEO company in Hong Kong then SEO Hong Kong will be the best for you.

And if we talk about asynchronous programming in the computer program then it allows the program to perform multiple tasks simultaneously in place of starting another task after completing one task. With asynchronous programming, operations in the program can be completed in a short duration of time.

For instance, a request is sent by the program to the server and simultaneously it is processing data and handling user input. With this program running efficiency will increase.

For building high-performance web applications asynchronous programming understanding is very essential for both fresher and seasoned programmers of javascript.

What is Synchronous Programming?

In the synchronous programming approach, computers perform one task at a time and perform these tasks in the order given by them in the form of instructions.

Just take an example of you working in a kitchen, and you have to do some tasks such as boiling water, cutting vegetables, and frying rice. And you are completing one task at a time. And after completing one task you are starting another task. So it will take a lot of time.

Synchronous programming will work similarly to the example given above, where the computer will complete one task before starting the execution of the next task. By this, it becomes easy to predict and understand what the computer is performing at a particular time.

Below is an example in javascript for showing the synchronous programming.

				
					// three functions are defined for performing three different tasks
function functionForTask1() {
  console.log("Working of Task 1");
}
function functionForTask2() {
  console.log("Working of Task 2");
}
function functionForTask3() {
  console.log("Working of Task 3");
}
// calling the functions for their execution
functionForTask1();
functionForTask2();
functionForTask3();

				
			

Output:

Working of Task 1

Working of Task 2

Working of Task 3

 

This code is executing each task in a series and moves on to the next task after completing one task.

Sometimes the synchronous programming approach becomes an issue. Mainly in the case when there is a task in the program which will be taking a very large time duration for its complete.

For instance, let us assume there is a synchronous program and it is waiting for the response from the server. And this program is not performing any other tasks this time. And stuck in waiting for the server response. This is called blocking and this application becomes unresponsive to the user.

				
					function someFunctionThatTakesLongTime() {
// getting current date
    let start = Date.now();
    while (Date.now() - 100< 5000) {
        //Do no task
    }
    return "Welcome";
}
console.log('Beginning..');
let res= someLongRunningFunction();
console.log(res);
console.log('...Ending);

				
			

In the lines of code given above:

  • First, it will display “Beginning..” on the console.
  • After that someFunctionThatTakesLongTime() is called in which some long-running tasks are performed which will take 10 seconds for its completion. And at the time of execution of this function rest of the program execution will be stuck().
  • JavaScript function then  returns welcome after its completion and it will be displayed on the console.
  • And at last “Ending.”. Will be displayed on the console.

When the execution of someFunctionThatTakesLongTime() takes place for about 10 seconds. At that time the program becomes unresponsive it will be blocked and there is no execution of the next line of the code. Due to this reason, the program takes more time its complete and also the application becomes unresponsive to the user.

But if the same code will execute asynchronously then, there will be no blockage of the code. The next line of the code will be executed properly. Due to this, the program will never become unresponsive and other code instructions will also execute when the program is waiting for the timeout to complete.

What is Asynchronous Programming?

The programming process in which a computer program can handle various tasks simultaneously instead of executing one task at a time is known as asynchronous programming.

It is possible in asynchronous programming to execute another task when the program is waiting for some other external events to happen such as network requests and so on. It can increase the responsiveness of the program and also improve its performance.

Let’s take an example, there is a program that retrieves data from a remote server at the same time it can execute other tasks also such as user input response, etc.

Let us understand the asynchronous programming approach with the help of an example using the setTimeout method:

				
					console.log("Starting");
setTimeout(function() {
  console.log("First timeout completed");
}, 2000);
console.log("Ending");

				
			

In the code given above, the function is executed by the setTimeout method after a specified time. And the function passed to the setTimeout will behave asynchronously as the execution of further lines of code will not stop at that time and the next lines will execute without waiting for the completion of timeout.

 

The output of the above code:

Start of script

End of script

First timeout completed

There are several techniques in JavaScript through which we can achieve synchronous programming. Callbacks are one of the most common techniques of asynchronous programming.

What is a callback function in JavaScript?

A callback function in a javascript is a function that is passed as an argument in another function after that which is invoked in the outer function for performing some type of task or routine.

How to Use a Callback Function

Let us take an example of you planning a birthday party and on the birthday you want to plan games, order cake and return gifts and want to invite guests apart from that you want to invite a clown for the guests’ entertainment. And a clown can only come to the party after all guests arrive and after doing all the arrangements for the party.

So you have invited the clown and told him that you will notify him after doing all the arrangements and the arrival of all guests. And here this clown will work just like a function and guests arriving are shown the function which is required to complete its execution before the execution of the callback function.

				
					Example of callback function:

// making a function 
function welcomeNote( callback) {
    console.log('Hi!!Welcome');
// calling callback function
   setTimeout(() => {
 callback();
  }, 2000);
}
// defining callback function
function callbackFuncEx() {
    console.log('Welcome to callback function');
}
// calling function by passing callback function as an argument
welcomeNote( callbackFuncEx);
console.log(“ending…”);

				
			

Output:

Hi!!Welcome

ending…

Welcome to callback function

In the above program, we have a function welcomeNote() which takes a callback as an argument and it uses a setTimeout() for the simulation of an asynchronous operation. To execute the callback function after a given period, the setTimeout method is used. The execution of the callback function takes place asynchronously, which shows that the execution of the next line of code is also working without waiting for the completion of the timeout.

You can see that the Welcome to callback function is executed after 2 seconds till the next line of code is executed.

This is the basic concept of asynchronous programming. There is no need to wait for the completion of the asynchronous operation. The execution of the next code continues without waiting.

What is Callback Hell?

A useful way to handle asynchronous operations is provided by callbacks. It may be possible that if callbacks are used in the nested form, then it makes the code complex and difficult to understand and read.

Sometimes this happens in a condition when there is the chaining of multiple callbacks and these callbacks create an indentation structure just like a pyramid is called callback hell or Pyramid of Doom.

				
					Example of callback hell:
fetchData(function(firstFunc) {
  fetchMoreData(firstFunc, function(secFunc) {
    fetchEvenMoreData(secFunc, function(thirdFunc) {
      fetchEvenEvenMoreData(thirdFunc, function(fourthFunc) {
        fetchFinalData(fourthFunc, function(finalData) {
          console.log(finalData);
        });
      });
    });
  });
});

				
			

It becomes difficult to maintain the code if there is a nesting of callbacks and the indentation makes the code structure more difficult to understand and read.

There is another modern way of handling asynchronous operations and avoiding callbacks hell. Promises are the better technique as compared to the callback function for handling asynchronous programming.

How Do Promises Work?

In javascript, a promise works just like a placeholder for storing the future action or value. By promise creation, you are saying the javascript engine promises to execute the particular task and once that task is completely executed or failed notify for that.

Promise attach callbacks function along with them to handle the outcome of the action. When the promise is fulfilled (successful completion of the action) or rejected( failure of the action), then only the callbacks will be invoked.

Promise Creation

The single argument is taken by the constructor i.e a function is known as the executor. And when the promise is created executor function is called immediately and two arguments are taken by the executor function i.e. a reject function and a resolve function.

For declaring a promise, you need to write a code given below:

				
					const promiseExample = new Promise(function(resolve, reject) {});

				
			

Now we will inspect the created object promiseExample by displaying it on the console.

				
					console.log(promiseExample );

				
			

As we can see in the output of promise object creation the promise has the status pending. This is showing like this as we have not set anything for the promise, so without any result or value it will always be pending.

Now let us take another example of a promise for displaying a string after 2 seconds on the console.

				
					const promiseExample= new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve("Hello! Welcome to promise example");
    }, 2000);
});

				
			

Now the promiseExample object is inspected, you will observe that now its status is fulfilled and the value passed to the resolve function is set to the string.

There are three states for a promise:

  • Pending: it is an initial state of promise, which means neither promise is fulfilled nor rejected.
  • Fulfilled: This state indicates an operation execution was completed.
  • Rejected: This state indicates an operation execution failed.

It’s important to note that a promise is said to be settled when it is resolved or rejected.

Now that you know how promises are created, let’s look at how you may consume them.

How to Consume a Promise

The following steps are involved in consuming the promise:

  • Obtaining a promise reference: Firstly it is required to obtain a reference of a promise for consuming a promise. In the example given above our promise reference object is promiseExample.
  • Attaching callbacks to the promise: After getting the reference, .then() and .catch() methods are used for attaching the callback functions to the promise. When a promise is fulfilled successfully then .then() is called and in case of promise rejection .catch() method will be called.
  • Wait for promise rejection or fulfillment: After attaching the callbacks to the promise, wait for the promise to be fulfilled or rejected.

Let us take an example for a better understanding of how the promise is consumed:

				
					promiseExample
    .then((result) => {
        console.log(result);
    })
    .catch((error) => {
        console.log(error);
    });

				
			

.then() callback method will be called with the resolved value after the promise is fulfilled. And .catch() will be called with an error message if the promise is rejected.

.finally() method can also be added, which is called when the promise is successfully settled. .finally() will always be called whether the promise has resolved or rejected status.

promiseExample

				
					  .then((result) => {
    console.log(result);
  })
  .catch((error) => {
    console.log(error);
  })
  .finally(() => {
//will always be executed whether the promise has resolved or rejected status.
     });

				
			

Async Functions with async/await

Asynchronous code can also be written in a more readable and synchronous way by the async/await feature

  • async keyword is used for asynchronous function declaration.

  • We use await keyword inside the async function for pausing the function execution till the resolution of the promise.

For asynchronous operation handling, async/await is a powerful tool and it makes the code more maintainable and readable by avoiding the need of using callbacks. With async/await asynchronous operations can be handled more intuitively. Writing the async keyword before the definition of the function and writing await keyword before asynchronous makes the code understandable and looks like just a synchronous operation code.

Conclusion

  •  In synchronous programming, computers will complete one task before starting the execution of the next task. 

  • The programming process in which a computer program can handle various tasks simultaneously instead of executing one task at a time is known as asynchronous programming.

  • Callbacks are one of the most common techniques of asynchronous programming.

  • A callback function in a javascript is a function that is passed as an argument in another function after that which is invoked in the outer function for performing some type of task or routine.

  • The chaining of multiple callbacks and these callbacks create an indentation structure just like a pyramid is called callback hell or Pyramid of Doom.

  • Promises are the better technique as compared to the callback function for handling asynchronous programming.

  • Asynchronous code can also be written in a more readable and synchronous way by the async/await feature