JavaScript Async Await

JavaScript Async Await with Examples

In this article, I am going to discuss JavaScript Async Await with Examples. Please read our previous article where we discussed JavaScript Promise Error Handling in detail. 

Async Await in JavaScript

In the past, to deal with asynchronous operations, we often used the callback functions. However, when we nest many callback functions, the code will be more difficult to maintain. And we end up with an unmanageable code issue which is known as the callback hell. So, to overcome this Promise came to rescue.

ES2017 introduced async and await build on top of promises and generators to write asynchronous actions inline. This makes asynchronous or callback code much easier to maintain and more readable.

Note: In order to understand how async and await works, we need to know how promises work.

Async in JavaScript:

Functions with the async keyword return a Promise and can be called with that syntax.
Syntax:
async function name([param[, param[, …param]]]) {
     statements
}

Here,

  1. name: The function’s name.
  2. param: The name of an argument to be passed to the function.
  3. statements: The statements comprising the body of the function. The await mechanism may be used.
Example:

async function f() {
return 1;
}

In an easy way, the word “async” before a function means a function always returns a promise. Other values are automatically wrapped in a resolved promise.

Await in JavaScript:

Inside an async function, the await keyword can be applied to any Promise and will make all of the function body after the await to be executed after the promise resolves.
Syntax:
async function f() {
    //Promise code goes here
    let value = await promise;// works only inside async functions
    return 1;
}

The keyword await, as the name describes it makes JavaScript wait until that promise settles and returns its result. It can be used within the async block only. It only makes the async block wait.

A function which is defined as async is a function that can perform asynchronous actions but still look synchronous. The way it’s done is using the await keyword to defer the function while it waits for a Promise to resolve or reject. For instance, with simple example resolving the promise after 2 seconds

<html>
<head>
    <title>JavaScript async and await example</title>
</head>
<body>
    <script>
        function resolveAfter2Seconds() {
            return new Promise(resolve => {
                setTimeout(() => {
                    resolve('resolved');
                }, 2000);
            });
        }

        async function asyncCall() {
            console.log('calling');
            const result = await resolveAfter2Seconds();
            console.log(result);
            // expected output: "resolved"
        }

        asyncCall();      
    </script>
</body>
</html>

Output:

JavaScript Async Await with Examples

An async function always returns a Promise itself, so we can use it in other asynchronous functions.

Async with a function expression in JavaScript

Besides the normal function, we can use the async keyword in a function expression. And the above example can be rewritten as

<html>
<head>
    <title>JavaScript async and await example with function expression</title>
</head>
<body>
    <script>
        function resolveAfter2Seconds() {
            return new Promise(resolve => {
                setTimeout(() => {
                    resolve('resolved');
                }, 2000);
            });
        }

        let asyncCall = async function() {
            console.log('calling');
            const result = await resolveAfter2Seconds();
            console.log(result);
            // expected output: "resolved"
        }

        console.log('first');
        asyncCall()
        console.log('second');
    </script>
</body>
</html>

Output:

Async with a function expression in JavaScript

Note that the console prints second before the “resolved”. This is due to using the await keyword.

Async with an arrow function in JavaScript

Async can be used with arrow function also. An example is given below for the same.

<html>
<head>
    <title>JavaScript async and await example with arrow function</title>
</head>
<body>
    <script>
        function resolveAfter2Seconds() {
            return new Promise(resolve => {
                setTimeout(() => {
                    resolve('resolved');
                }, 2000);
            });
        }

        let asyncCall = async () => {
            console.log('calling');
            const result = await resolveAfter2Seconds();
            console.log(result);
            // expected output: "resolved"
        }

        console.log('first');
        asyncCall()
        console.log('second');
    </script>
</body>
</html>

Output:

Async with an arrow function in JavaScript

JavaScript Async with class methods
<html>
<head>
    <title>JavaScript async and await example with class methods</title>
</head>
<body>
    <script>
        function resolveAfter2Seconds() {
            return new Promise(resolve => {
                setTimeout(() => {
                    resolve('resolved');
                }, 2000);
            });
        }

        class Greeter {
            async asyncCall() {
                console.log('calling');
                const result = await resolveAfter2Seconds();
                console.log(result);
                // expected output: "resolved"
            }
        }

        let gtr = new Greeter();
        console.log('first');
        gtr.asyncCall();
        console.log('second');
        
    </script>
</body>
</html>

Output:

JavaScript Async with class methods

Note that if we use the await operator outside of an async function, we will get an error.

JavaScript Async Await Error handling

The error handling behavior of async/await is the same as the error handling of promises we saw in the previous chapter. If a promise resolves, then await promise returns the result. However, but when the promise gets rejected, the await promise will throw an error as if there were a throw statement.

JavaScript Async Await Error handling

In real situations, the promise may take some time before it rejects it. In that scenario, there will be a delay before await throws an error.

Try/catch with reject() method

We can catch the error by using the try…catch statement, the same way as a regular throw statement:

<html>
<head>
    <title>JavaScript async and await with error handling-try/catch example</title>
</head>
<body>
    <script>
        function resolveAfter2Seconds(value) {
            return new Promise((resolve, reject) => {
                if (value === undefined) {
                    reject(new Error('invalide value argument'))
                }
                setTimeout(() => {
                    resolve(`resolve: ${value}`);
                }, 2000);
            });
        }

        async function asyncCall() {
            try {
                console.log('calling');
                const result = await resolveAfter2Seconds();
                console.log(result);
            }
            catch (error) {
                console.log(`caught by try/catch: ${error} `);
            }
        }

        asyncCall();
    </script>
</body>
</html>

Output:

Try/catch with reject() method

Chaining Promises with try/catch

If we have chain promises and in that, if there is an error raised by one or more await promises we can catch that error

<html>
<head>
    <title>JavaScript async and await with error handling-chain promise example</title>
</head>
<body>
    <script>
        function resolveAfter2Seconds(value) {
            return new Promise((resolve, reject) => {
                if (value === undefined) {
                    reject(new Error('invalide value argument'))
                }
                setTimeout(() => {
                    resolve(`resolve: ${value}`);
                }, 2000);
            });
        }

        async function asyncCall() {
            try {
                console.log('calling');
                const result1 = await resolveAfter2Seconds(1);
                const result = await resolveAfter2Seconds();
                console.log(result);
            }
            catch (error) {
                console.log(`caught by try/catch: ${error} `);
            }
        }

        asyncCall();
    </script>
</body>
</html>

Output:

Chaining Promises with try/catch

Catch() method

Inside the promise, the catch() method will catch the error produce by the throw statement and reject(). If we don’t have try/catch then the error raised in promises by the call of async function rejected. We can use .catch() method to handle it.

<html>	
<head>
    <title>JavaScript async and await with error handling-catch() method example</title>
</head>
<body>
    <script>
        function resolveAfter2Seconds(value) {
            return new Promise((resolve, reject) => {
                if (value === undefined) {
                    reject(new Error('invalide value argument'))
                }
                setTimeout(() => {
                    resolve(`resolve: ${value}`);
                }, 2000);
            });
        }

        async function asyncCall() {
            console.log('calling');            
            const result = await resolveAfter2Seconds();
            console.log(result);
        }

        asyncCall()
            .catch(error => console.log(`caught by .catch: ${error} `));
    </script>
</body>
</html>

Output:

JavaScript Async Await with Examples

Unhandled rejected by missing the catch() method

An error will be silently ignored if a promise doesn’t have a catch() block or reject() handler. If any error occurs and we don’t have the catch() method, the JavaScript engine issues a runtime error and stops the execution of the program.

<html>
<head>
    <title>JavaScript async and await with error handling- missing the catch() method example</title>
</head>
<body>
    <script>
        function resolveAfter2Seconds(value) {
            return new Promise((resolve, reject) => {
                if (value === undefined) {
                    reject('invalide value argument')
                }
                setTimeout(() => {
                    resolve(`resolve: ${value}`);
                }, 2000);
            });
        }

        async function asyncCall() {          
                console.log('calling');
                const result = await resolveAfter2Seconds();
                console.log(result);            
        }

        asyncCall()
           
    </script>
</body>
</html>

Output:

Unhandled rejected by missing the catch() method

If we forget to add .catch() method there, then we will get an unhandled promise error (viewable in the console). We can catch such errors using a global unhandled rejection event handler as described in the previous chapter of Error handling with promises.

Async/Await works well with Promise.all() method in JavaScript

It worked great with promise.all() method, when we need to wait for multiple promises we can bind them in Promise.all() which accept the list of iterables (e.g.: array) and then to wait. Below is the example that elaborate it more

<html>
<head>
    <title>JavaScript async and await with error handling- Promise.all() method example</title>
</head>
<body>
    <script>
        function resolveAfter2Seconds(value) {
            return new Promise((resolve, reject) => {
                if (value === undefined) {
                    reject('invalide value argument')
                }
                setTimeout(() => {
                    resolve(`resolve: ${value}`);
                }, 2000);
            });
        }

        async function asyncCall() {
            // wait for the array of results
            let result = await Promise.all([
                resolveAfter2Seconds(10),
                resolveAfter2Seconds(12)]);
            console.log(result);
        }

        asyncCall();
    </script>
</body>
</html>

Output:

Async/Await works well with Promise.all() method in JavaScript

In case of any error, it jumped from failed promise to the promise.all() and then becomes an exception that we can catch using try…catch by wrapping around the method call.

Async/await with try/catch in JavaScript

When we use async/await we hardly use .then() method, as await handles the waiting for us. And we can use a regularly try…catch instead of .catch(). That’s usually (but not always) more convenient.

But when we’re outside of an async function, we’re syntactically unable to use await, so it’s a normal practice to add .then/catch to handle the final result or falling-through error.

Here, in this article, I try to explain JavaScript Async Await with Examples. I hope this JavaScript Async Await with Examples article will help you with your need. I would like to have your feedback. Please post your feedback, question, or comments about this JavaScript Async Await.

Leave a Reply

Your email address will not be published. Required fields are marked *