Deep dive into Asynchronous Javascript
Tags: javascript, asynchronous, webdev, developers
Published: 2021-06-16 00:54:29

In this article we'll be covering callbacks, promises and async/await as these are the ways to deal with asynchronous data.

To understand asynchronous, you'll first have to understand synchronous.

#### What is synchronous?

Synchronous is when something is done in sequence. In programming terms synchronous is when a bunch of code are executed one after the other.

For example

```js
function A() {
  console.log("Task 1");
  console.log("Task 2");
  console.log("Task 3");
}
A();
```

In the example above the code will run synchronously.

```terminal
Task 1
Task 2
Task 3
```

It prints `Task 1`, `Task 2`, and `Task 3` one after the other. It will wait for every line to complete its execution.

#### What is asynchronous?

Asynchronous is nothing but just the opposite of synchronous. You keep doing things while others are getting completed.
What do you think the code will print?

```js
console.log("Task 1");
setTimeOut(() => {
  console.log("Task 2");
}, 1000);
console.log("Task 3");
```

well the above code will print

```terminal
Task 1
Task 3
Task 2
```

Why does it print that way? It is because setTimeout function is not called immediately. It is called after 1 second. Till the time it waits the third console.log() gets printed.

#### Why Asynchronous Javascript?

When a JavaScript code is executed, the synchronous code blocks further execution until it completes what it's doing. Code which takes long to complete can make the UI/server unresponsive until the function has returned, which result in a terrible user-experience.

**For instance:** You want the latest comments of your blog from a server and render in your blog, and it is done synchronously, then a visitor who is in your blog site won't be able to do other things until those comments are loaded. Which indeed could cause a long delay before they could read the comments in your blog.
To understand the above example, follow the code:

```js
const comments = loadCommentsFromDatabaseSync();

displayBlogInWebPage();
```

In the above code, in order to display the blog on website, the website will first have to wait for `loadCommentsFromDatabaseSync()` to get complete. Once `loadCommentsFromDatabaseSync()` is completed then only it will display the blog in the web page.

By using `async`

```js
const comments = loadCommentsFromDatabaseAsync();

displayBlogInWebPage();
```

In the above code `displayBlogInWebPage()` will not wait for the completion of `loadCommentsFromDatabaseAsync()`.

> We should use asynchronous programming when performing expensive and time-consuming operations.

## Different ways of Asynchronous programming

In javascript, there are three ways to accomplish asynchronous programming, namely `callback`, `promises` and `async/await`.
Let us get in detail with example.:

### Callback

**What is a callback?**

A callback is a function which is executed after a subsequent function has finished executing.

As JavaScript functions are also a type of `object` and they can be passed as an argument while calling a function so much like any other objects like `string`, `number` etc.
Example:

```js
function addTwoNumbers(a, b, callback) {
  console.log("Addition of two numbers: ", a + b);
  callback();
}

function print() {
  console.log("This must be printed after addition to the console");
}

addTwoNumbers(2, 3, print);
```

The output of the above code:

```terminal
Addition of two numbers: 5
This must be printed after addition to the console
```

In the above example, we have two functions:

**addTwoNumbers(a,b,callback):** This functions is called with there arguments `a`,`b` and `callback`, where `a` and `b` are `numbers` while the third argument `callback` is a function. The addTwoNumbers() prints the addition of the two numbers, and as soon as that completes its execution, the callback function is fired!

> This type of function is also known as the `callback function`.

**print():** As soon as addTwoNumbers() completes its execution and call the callback function this print() will get called and prints its output to the console.

Callbacks are mainly used for handling asynchronous operations like – making an API request to the server, fetching/writing some data from/into a file, registering event listeners etc. Callbacks are used for the mentioned operations. Depeneding on the result of the operation the callback function will be executed.

### Promises

To understand the basic of promises please check-out <a href="https://pratapsharma.in/fundamentals-of-javascript-every-developer-should-know/#5-promises" target="_blank">Basic of Promises</a>.

**This will be the continuation of the above link.**

#### basic syntax of promise in javascript.

```js
let promise = new Promise(function (resolve, reject) {
  //resolve or reject is done here
});
```

As discussed in the basics of Promises section promises have three states, and the states are self-explanatory:  
**Pending**: Pending is a state when the promise is neither resolved or rejected. It will continue to remain indefinitely `pending` unless it gets resolved or rejected.  
**Resolved**: A promise is resolved when the resolve method is called from the promise. The resolved promise will be consumed in the `.then()` section.  
**Rejected**: If the reject function was called from the promise, then the promise is rejected. If the promise is rejected, then it should be consumed in the `.catch()` section.

#### Consuming a promise

Please check the above link in order to see consuming promises.

#### Chaining of promises

In order to understand the concepts of Async/await, one has to understand the core usage of promise, which includes `chaining of promises`.

> When a .then() method returns a promise, then the subsequent executions of the `.then()` are suspended until the current promise block is resolved.

```js
let firstPromise = new Promise(function (resolve, reject) {
  setTimeout(resolve, 1000, "Pratap");
});

let secondPromise = new Promise(function (resolve, reject) {
  setTimeout(resolve, 2000, "Prasar");
});

let thirdromise = new Promise(function (resolve, reject) {
  setTimeout(reject, 3000, "Error");
});

firstPromise
  .then((x) => {
    console.log("First Promise after 1 sec: ", x);
    return secondPromise;
  })
  .then((x) => {
    console.log("Second Promise after 2 sec: ", x);
    return thirdromise;
  })
  .catch((e) => {
    console.log("Third Promise after 3 sec: ", e);
  });
```

The output of the above code:

```terminal
First promise after 1 sec:  Pratap
Second promise after 2 sec: Prasar
Third promise after 3 sec: Error
```

**Explanation** of above code.

Let us understand step by step:

- We have initialised 4 promises `firstPromise`, `secondPromise`, `thirdPromise` and `fourthPromise`. For the first instance, all four promises are racing toward resolve/reject.
- After 1 second the `firstPromise` gets resolved as we are calling the `resolve` method in the promise initialization and this gets printed in the console `First promise after 1 sec: Pratap`. Then we return another promise `secondPromise`.
- After 2 seconds the `secondPromise` also gets `resolved` and `Second promise after 2 sec: Prasar` gets printed to the console. We then return `thirdPromise` from the `secondPromise`.
- But, after 3 seconds the `thirdPromise` gets rejected as we called `reject` in the `thirdPromise` initialization. `Third promise after 3 sec: Error` gets printed to the console.

#### Promise.all

`Promise.all` accepts an array of promises, and will attempt to fulfil all the promises. If any of the promises are rejected, then the promise will exit.

In order to fulfil multiple promises, `promise.all` was introduced. It is widely used in javascript frameworks where we want to get data from multiple `APIs`. So rather then calling the promises individually you'd better want to use `Promise.all()` method and handle the result based on the status of the promises.

An example of `promise.all`:

```js
const arrayOfPromises = [new Promise(promise1), new Promise(promise2)];

function runAllThePromises() {
  Promise.all(arrayOfPromises).then(showSuccessMessage).catch(showErrorMessage);
}

arrayOfPromises();
```

#### Promise.race

`promise.race()`method returns a promise which fulfills or rejects as soon as one of the promises in an array gets fulfills or rejects.

We can understand `promise.race()` as the realtime race.

Suppose five people are participating in a race and any of them crosses the winning line then the race ends. Also, if any of them gets injured, then also the race gets end.

```js
const firstPromise = new Promise((resolve, reject) => {
  setTimeout(resolve, 2000, "First Promise");
});

const secondPromise = new Promise((resolve, reject) => {
  setTimeout(resolve, 1000, "Second Promise");
});

Promise.race([firstPromise, secondPromise]).then((value) => {
  console.log(value);
});
```

Output:

```terminal
Second Promise
```

**Explanation:**

We passed `firstPromise` and `secondPromise` as an array in the argument of `Promise.race()`. As `secondPromise` gets resolved faster than `firstPromise` so `Second Promise` gets printed in the console.

#### Async/Await

Async/Await is one of the most recent additions to the JavaScript language which is part of ES8.

Async/Await is syntactic sugar on top of promises which makes asynchronous code easier to write and to read. The async code is written just like the synchronous code. It is just a special syntax to work with promises in a more synchronous-type manner.

Basic function:

```js
const getFruit = () => {
  return "Mango";
};
```

The above snippet just a basic javascript code which returns `Mango`.

#### async

Now, let us convert the above code to promise using `async` keyword.

```js
const getFruit = async (name) => {
  const fruits = ["Apple", "Banana", "Mango"];

  return fruits[name];
};
```

Now, in the function above, just adding `async` keyword in front of a function, not the function will return a `Promise`.

```js
getFruit("Apple").then((res) => {
  console.log(res);
}); // prints: Apple
```

#### await

The `await` keyword is used to wait for a Promise to get resolved. `await` can be used inside an Async function block only. It makes JavaScript wait until the promise returns a result. It only makes the async function block wait and not the whole program execution.

```js
async function demonstrateAsync() {
  let promise = new Promise((resolve, reject) => {
    setTimeout(() => resolve("Promise is ressolved!"), 1000);
  });

  // wait until the promise returns us a value
  let result = await promise;

  console.log(result);
}

demonstrateAsync();
```

The output of the above code:

```terminal
Promise is ressolved!
```

> `await` should be used within an `async` block only.  
> `await` can't be used in top-level code

#### Catching error in async/await

Handling errors in async/await is pretty straight forward. In order to handle an error, we just have to wrap inside a `try..catch` block.

```js
async function thisThrowsError() {
  try {
    let response = await fetch("http://invalidUrl");
  } catch (err) {
    console.log("Error: ", err); // Invalid url
  }
}
thisThrowsError();
```

Any error in the scope of `try` block will be handled in the `catch` block.

### Conclusion

In this blog, we have completed the different ways of asynchronous programming in Javascript and their usage.

Due to the addition of asynchronous programming in javascript, it makes it possible to express waiting for long-running actions without blocking the execution of code. In javascript, it is typically implemented using `callback`, `promises` and `async/await`.

Programming asynchronously in Javascript is made easier by using promises and async/await, which allow us to write an asynchronous program as if it were synchronous.

### FURTHER READING

- <a href="https://pratapsharma.io/things-to-keep-in-mind-before-learning-javascript-framework/" target="_blank">Things to keep in mind before starting Javascript framework</a>
- <a href="https://pratapsharma.io/introduction-to-strapi-a-nodejs-headless-cms/" target="_blank">Strapi.js - Open Source Node.js Headless CMS</a>
- <a href="https://pratapsharma.io/difference-between-var-let-const-in-javascript/" target="_blank">var, let, and const – Why to avoid var 😷 and how to put the other two to good use? - Javascript</a>

💌 If you’d like to receive more tutorials in your inbox, you can sign up for the newsletter [here](https://pratap.substack.com).