async await in javascript

Understanding How To Use Async Await In JavaScript

It was only recently that I came across a scenario where I had used async await to solve a particular use case. In this tutorial, you’ll learn what is async await in JavaScript and how to use it.

This tutorial assumes that you are familiar with Promises in JavaScript.

A Brief Intro To Async Await In JavaScript

Let’s try to understand the concept of async await with the help of an example. Let’s write a simple code to make API call from Node.js.

Create a folder called ApiProject. Navigate to the project directory and initialize the Node project using Node Package Manager (npm).

mkdir ApiProject
cd ApiProject
npm init

Create a file called app.js. Inside app.js create a method called make_API_call which will make use of the request module to make the API call to REST endpoint.

Here is how app.js file looks:

const request = require('request')

/*
 * Method to make API call
 * using the request node module
 * Returns a promise
*/
function make_API_call(){
    return new Promise(function(resolve, reject){
        request.get('https://jsonplaceholder.typicode.com/todos/1', function(error, response, body){
            if (error) reject(error)
            resolve(body)
        })
    })
}

/* Make a call to the make_API_call method,
 once resolved the response will be logged to console */
make_API_call()
.then(function(response){
    console.log(response)
})
.catch(function(error){
    console.log('Error ', error)
})

As seen in the above piece of code, the make_API_call method returns a promise which when resolved logs the output to console.

The above code looks and works fine but using async and await in JavaScript you can write the above code in a synchronous manner.

Let’s have a look how you can modify the above code using async and await in JavaScript.

const request = require('request')

/*
 * Method to make API call
 * using the request node module
 * Returns a promise
*/
function make_API_call(){
    return new Promise(function(resolve, reject){
        request.get('htps://jsonplaceholder.typicode.com/todos/1', function(error, response, body){
            if (error) reject(error)
            resolve(body)
        })
    })
}

/*
 * The async method makes a call to the make_API_call
 * method and waits until the promise is resolved
*/
async function callAPI(){
    try{
        let response = await make_API_call()
        console.log(response)
    } catch(e){
        console.log('error ', e);
    }
} 
callAPI()

The await keyword works only inside an async function. To catch any errors thrown inside the await method you need to add a try and catch block. The above code looks synchronous and bit more cleaner and easier to read as compared to the earlier piece of code.

Use Case To Implement

You have an object array. Each object inside the array has user array. You need to iterate the users array inside each object, make an API call using the user ids and append the response corresponding to each user id in separate array.

Here is how the object array looks like:

[{
    "id": 1,
    "users": [1, 2]
}, {
    "id": 2,
    "users": [3.4]
}]

Once you have implemented the use case, here is how the response will look like:

[{
    "id": 1,
    "users": [1, 2],
    "userInfo": [{
        "id": 1,
        "info": {
            "userId": 1,
            "id": 1,
            "title": "delectus aut autem",
            "completed": false
        },
        "id": 2,
        "info": {
            "userId": 2,
            "id": 2,
            "title": "delectus aut autem",
            "completed": false
        }
    }]
}, {
    "id": 2,
    "users": [3, 4],
    "userInfo": [{
        "userId": 1,
        "id": 3,
        "title": "fugiat veniam minus",
        "completed": false
    }, {
        "userId": 1,
        "id": 4,
        "title": "et porro tempora",
        "completed": true
    }]
}]

You can accomplish this using Promise as well as async await in JavaScript. Let’s first have a look at how you can solve this using Promise.all. What you need to do is loop through the data object and make API call for each user in the list. Each API call will return a promise which you can store in an array. Use Promise.all to know when a list of promises has been resolved for a particular data set. Here is how the code looks :

/*
 * Method to make API call
 * using the request node module
 * Returns a promise
*/
function make_API_call(id){
    return new Promise(function(resolve, reject){
        if(id == 1 || id == 2){
            request.get('https://jsonplaceholder.typicode.com/todos/' + id, function(error, response, body){
                if (error) reject(error)
                setTimeout(function(){
                    resolve(body)
                }, 5000)
            })
        }
        else if(id == 3 || id == 4){
            request.get('https://jsonplaceholder.typicode.com/todos/' + id, function(error, response, body){
                if (error) reject(error)
                setTimeout(function(){
                    resolve(body)
                }, 1000)
            })
        }
    })
}

const data = [{
    "id": 1,
    "users": [1, 2]
},{
    "id": 2,
    "users": [3, 4]
}];

let counter = 0;
let promise;

for(let i = 0;i < data.length; i++){
    promises = []
    for(let user = 0; user < data[i]['users'].length; user++) {
        promises.push(make_API_call(data[i]['users'][user]))
    }
    Promise.all(promises)
    .then(function(response){
        counter++
        data[i]['userInfo'] = response
        if(counter == data.length) console.log('response ', data) 
    })
}

The same functionality can be achieved using async await in JavaScript. Let have a look at the code :

const data = [{
    "id": 1,
    "users": [1, 2]
},{
    "id": 2,
    "users": [3, 4]
}];

/*
 * Async method defined to enable async await
 * functionality
*/
async function do_work(){
    for(let i = 0;i < data.length; i++){
        let promises = []
        for(let user = 0; user < data[i]['users'].length; user++) {
            promises.push(make_API_call(data[i]['users'][user]))
        }
        let result = await Promise.all(promises)
        data[i]['userInfo'] = result
        if(i == data.length - 1) console.log(data)
    }   
}

do_work()

Use of async await has done away with the use of .then from the code. The code looks like synchronous code and is more readable.

Wrapping It Up

In this tutorial, you learnt about async await in JavaScript and how to use it in your application. Have you used async await or Promises in your application. How was your experience with Promise and async await in JavaScript ? Do let us know in the comments below.