How to synchronize your JavaScript function calls with async and await

When ECMAScript 2017 was finalised in June 2017, we get the async/await constructs that simplify synchronous JavaScript function calls.

Therefore, you may want to use async and await to keep your JavaScript lean.

In case you need it, this post shows how you can synchronize your JavaScript function calls with async and await.

Understand what async do to your JavaScript function

First, let us look at the async construct. We typically place the async construct in front of a JavaScript function:

async function add(x, y) {
    return x + y;
}

When we place the async construct before the add function, the return value is magically wrapped in a JavaScript Promise. Given that, we can call our add function in the following way:

add(1, 3).then(alert);

When the JavaScript code is ran by a compatible browser, we will see 4 appearing in an alert window.

Understand what await does to your JavaScript function call

When you put await before a Promise, you make your JavaScript interpreter wait until that Promise is able to return a result.

For example, in the following JavaScript code segment, the alert function will only run after 1 second:

async function showAdditionResult() {

    promiseToAdd = new Promise(function (resolve, reject) {
        setTimeout(function () { 
            resolve(add(1, 3));
        }, 1000)
    });

    result = await promiseToAdd; 

    alert(result); 

}
showAdditionResult();

This is because the await function will block the interpreter till setTimeout function performs the addition. Therefore, the alert function will make the browser show an alert window with 4 in the dialog body without fail.

If we want to achieve similar behaviour without the await construct, then we will have to put the alert function within the then() function of promiseToAdd:

function showAdditionResult() {

    promiseToAdd = new Promise(function (resolve, reject) {
        setTimeout(function () { 
            resolve(add(1, 3));
        }, 1000)
    });

    promiseToAdd.then(
        function(result) {
            alert(result); 
        }
    ); 

}
showAdditionResult();

Indeed by comparing both versions, we can see that the await construct can help enhance the readability of synchronous JavaScript codes.

Uncaught SyntaxError: await is only valid in async function

If we use await in a regular JavaScript function, then the interpreter will throw us a syntax error.

For example, our JavaScript interpreter will not be able to interpret the following JavaScript function:

function showAdditionResult() {

    promiseToAdd = new Promise(function (resolve, reject) {
        setTimeout(function () { 
            resolve(add(1, 3));
        }, 1000)
    });

    result = await promiseToAdd; 

    alert(result); 

}

showAdditionResult();

When we attempt to run the above JavaScript codes in a Chrome browser, we will see the following error message in the console:

Uncaught SyntaxError: await is only valid in async function

Catch errors that may happen

In order to see how errors can be caught while we use the await function, let's define an async function that attempt to fetch from a URL:

async function fetchData(url) {

    response = await fetch(url);
    
    if (response.ok) {
        return response.json();
    }
    else {
        throw new Error(response.status);
    }
}

Since fetch only reject on network failure or if anything prevented the request from completing, we explicitly throw an Error on HTTP error status.

Given that, we try to catch Errors throw by the fetchData function. When we use the await construct, we will be able to catch errors easily.

In order to do so, we simply wrap the function call in a try-catch block:

async function testFetches() {
    try {
        jsonData = await fetchData('https://httpbin.org/headers');
        alert(JSON.stringify(jsonData));

        jsonData = await fetchData('https://httpbin.org/status/500');
        alert(JSON.stringify(jsonData));    

    } catch(err) {
        alert(err);
    }
}

testFetches();

When we ran the two previous JavaScript code segments, we simulate a scenario to catch Error.

Since a HTTP request made to https://httpbin.org/headers will return a response with 200 OK, we will be able to show an alert with the JSON data from the response body.

However, when we try to make a HTTP request to https://httpbin.org/status/500, an Error will be thrown. When that happens, the browser will show Error: 500 in an alert window.

About Clivant

Clivant a.k.a Chai Heng enjoys composing software and building systems to serve people. He owns techcoil.com and hopes that whatever he had written and built so far had benefited people. All views expressed belongs to him and are not representative of the company that he works/worked for.