mrizwanashiq

Muhammad Rizwan Ashiq

Posted on June 26, 2023

Async Await

What is Async Await

async/await is a language feature introduced in ECMAScript 2017 (AKA ES8) that makes it easier to work with asynchronous code in JavaScript. It allows you to write asynchronous code that looks and behaves like synchronous code, using the await keyword to pause execution until a Promise is resolved.

async/await is a syntactic sugar over the promises. It makes asynchronous code look like synchronous code. It is a new way to write asynchronous code in JavaScript.

Let's see them individually.

async

The async keyword is used to declare an asynchronous function. What happens when you use the async keyword?

It executed asynchronously, meaning that it doesn't block the execution of the program while it's waiting for a certain task to complete. Instead, it returns a Promise that represents the result of the asynchronous operation.

async functions are typically used when dealing with time-consuming operations such as network requests, file I/O, or database queries, where waiting for the result would block the execution of the program. By using async functions, you can avoid blocking and allow the program to continue executing other tasks while waiting for the result.

It Allows you to write promises-based code as if it was synchronous. It ensures that the execution thread is not being broken. The event loop is used for its asynchronous operation. A value is always returned by async functions. It guarantees that promises be fulfilled, and if they are not, JavaScript automatically wraps them in promises that are resolved with their values.

async function myFunction() {
    return "Hello World";
}
Enter fullscreen mode Exit fullscreen mode

The above function returns a promise. The promise is resolved with the value "Hello World".

And in the arrow function:

const myFunction = async () => {
    return "Hello World";
};
Enter fullscreen mode Exit fullscreen mode

await

await keyword is used to wait for a Promise to resolve before proceeding to the next line of code. It can only be used inside an asynchronous function (a function that has been declared with the async keyword).

When an async function encounters an await keyword, it pauses its execution until the Promise that is being awaited has been resolved. The value of the resolved Promise is then returned and assigned to the variable that follows the await keyword.

Here's an example of how await can be used:

async function getData() {
    const response = await fetch("https://example.com/data");
    const data = await response.json();
    return data;
}

getData().then((data) => {
    console.log(data);
});
Enter fullscreen mode Exit fullscreen mode

In the example above, the getData function is declared as async, which allows us to use the await keyword inside it. The function first makes a network request to fetch some data from the specified URL. We then wait for the response to come back using await, and then we wait again for the data to be parsed into a JSON object. Finally, we return the parsed data from the function.

When we call getData(), it returns a Promise that resolves to the parsed data. We can then use .then() to log the data to the console once it's been resolved.

async/await vs promises

async/await is modified version (wrapper) of promises. async/await just replaces the .then() and .catch() methods with await keyword and try and catch blocks. It is a syntactic sugar over promises. It makes asynchronous code look like synchronous code. It is a new way to write asynchronous code in JavaScript.

async/await

async function myFunction() {
    const fetchData = async () => {
        const res = await fetch(resource);
        const data = await res.json();
        return data;
    };

    const result = await fetchData(); // wait till the promise resolves (*)

    console.log(result); // "Promise was resolved"
}
Enter fullscreen mode Exit fullscreen mode

promises

function myFunction() {
    const fetchData = () => {
        return fetch(resource)
            .then((res) => res.json())
            .then((data) => data);
    };

    fetchData().then((result) => console.log(result)); // "Promise was resolved"
}
Enter fullscreen mode Exit fullscreen mode

Both the above code snippets do the same thing. The only difference is that the async/await version is easier to read and write. But in some cases, where I need to run multiple promises in parallel, I prefer to use promises instead of async/await. Because async/await will wait for the previous promises to resolve before moving to the next line of code. But in promises, I can run multiple promises in parallel like this

Examples

HTTP requests with async/await

Here's an example of using async/await to make an HTTP request:

// to use async/await, you must use a function that is labeled as `async`, like this:
async function getData() {
    try {
        const response = await fetch("https://example.com/");
        // `await` will pause the execution of the function until the Promise is resolved
        const data = response.json();
        console.log(data);
    } catch (error) {
        // if there is an error, it will be caught here
        console.error(error);
    }
}

getData(); // calling the function
Enter fullscreen mode Exit fullscreen mode

In this example, we define an async function called getData. Inside the function, we use the await keyword to pause execution until the fetch Promise is resolved.

If there is an error making the request, the catch block will be executed.

async/await makes it easier to work with asynchronous code in JavaScript and can help make your code more readable and maintainable. It is particularly useful for working with Promises and is widely used in modern JavaScript code.

:::info

async/await is a language feature that is built on top of Promises. It is not a replacement for Promises. It is a syntactic sugar that makes asynchronous code look and behave like synchronous code.

If you are new to Promises, you should read the Promises article first.

:::

async/await with Promises

Here's an example of how to use async/await with a Promise:

async function getData() {
    try {
        const response = await fetch("https://example.com/");
        const data = await response.json();
        return data;
    } catch (error) {
        console.error(error);
    }
}

getData()
    .then((data) => {
        console.log(data);
    })
    .catch((error) => {
        console.error(error);
    });
Enter fullscreen mode Exit fullscreen mode

In this example, we define an async function called getData. The await operator is used to wait for the resolved value of a Promise. In this case, we use it to wait for the fetch function to complete and for the json method to complete.

If the Promise is rejected, the catch block will be executed.

async/await with for loops

Here's an example of how to use async/await with a for loop:

async function getData() {
    try {
        const response = await fetch("https://example.com/");
        const data = await response.json();
        return data;
    } catch (error) {
        console.error(error);
    }
}

async function getMultipleData() {
    const data = [];
    for (let i = 0; i < 5; i++) {
        const response = await getData();
        data.push(response);
    }
    return data;
}

getMultipleData()
    .then((data) => {
        console.log(data);
    })
    .catch((error) => {
        console.error(error);
    });
Enter fullscreen mode Exit fullscreen mode

In this example, we define an async function called getData. The await operator is used to wait for the resolved value of a Promise. In this case, we use it to wait for the fetch function to complete and for the json method to complete.

If the Promise is rejected, the catch block will be executed.

async/await with Promise.all() and Promise.settleAll() methods

Imagine a situation where you have to make multiple HTTP requests and put await in front of each request, in result you have to wait for all of them to complete sequentially, and it would take a lot of time, as you can see in the example below:

```js title="sequential requests"
async function getData() {
try {
const users = await getUser();
const posts = await getPosts(); // wait for the previous request to complete
const comments = await getComments(); // wait for the previous request to complete
const followers = await getFollowers(); // vice versa
const following = await getFollowing();
const likes = await getLikes();

    return {
        users,
        posts,
        comments,
        followers,
        following,
        likes,
    };
} catch (error) {
    console.error(error);
}
Enter fullscreen mode Exit fullscreen mode

}




You can see that we have to wait for each request to complete before moving on to the next one. This is where `Promise.all` comes in handy.

#### `Promise.all`

It allows you to hit multiple async processes at the same time (in parallel) and wait for all of them to complete. Here's an example:



```js title="parallel requests"
async function getData() {
    try {
        const usersPromise = getUser(); // no await here
        const postsPromise = getPosts(); // no await here
        const commentsPromise = getComments(); // vice versa
        const followersPromise = getFollowers();
        const followingPromise = getFollowing();
        const likesPromise = getLikes();

        // wait for all promises to resolve, and then destructure the result
        const [users, posts, comments, followers, following, likes] =
            await Promise.all([
                usersPromise,
                postsPromise,
                commentsPromise,
                followersPromise,
                followingPromise,
                likesPromise,
            ]);

        /**
         * or you can use the following syntax if you don't need to use the promises again
         * which is more concise and readable, and I prefer this syntax
         *
         * const [users, posts, comments, followers, following, likes] = await Promise.all([
         *     getUser(),
         *     getPosts(),
         *     getComments(),
         *     getFollowers(),
         *     getFollowing(),
         *     getLikes(),
         *  ]);
         *
         */

        return {
            users,
            posts,
            comments,
            followers,
            following,
            likes,
        };
    } catch (error) {
        console.error(error);
    }
}
Enter fullscreen mode Exit fullscreen mode

In this example, we use Promise.all to wait for all the promises to be resolved and then we destructure the array to get the resolved values. These are parallel requests, which means that the requests are made at the same time.

Promise.allSettled

But Promise.all has a problem, imagine a situation where one of the promises is rejected, in this case, the whole promise will be rejected and the catch block will be executed. If we want to get the resolved values, and ignore the rejected ones, we can use Promise.allSettled:

async function getData() {
    try {
        const [users, posts, comments, followers, following, likes] =
            await Promise.allSettled([
                getUser(),
                getPosts(),
                getComments(),
                getFollowers(),
                getFollowing(),
                getLikes(),
            ]);

        return {
            users,
            posts,
            comments,
            followers,
            following,
            likes,
        };
    } catch (error) {
        console.error(error);
    }
}
Enter fullscreen mode Exit fullscreen mode

In this example, we use Promise.allSettled to wait for all the promises to be resolved or rejected and then we destructure the array to get the resolved values.

async/await in series

Promise.all and Promise.allSettled are useful if all the promises are independent of each other, but if you have a situation where you have to wait for one promise to be resolved before moving on to the next one. You can also use Promise.all, or Promise.allSettled for few promises, and then await the next promise, as shown in the example below:

async function getData() {
    try {
        const [users, posts, comments] = await Promise.all([
            getUser(),
            getPosts(),
            getComments(),
        ]);

        const followers = await getFollowers();
        const following = await getFollowing();
        const likes = await getLikes();

        return {
            users,
            posts,
            comments,
            followers,
            following,
            likes,
        };
    } catch (error) {
        console.error(error);
    }
}
Enter fullscreen mode Exit fullscreen mode

In this example, we use Promise.all to wait for the first three promises to be resolved, and then we await the next three promises.

Conclusion

In this article, we learned about async/await and how to use it with Promises. We also learned how to use async/await with for loops and how to use async/await with Promise.all and Promise.allSettled methods.

💖 💪 🙅 🚩
mrizwanashiq
Muhammad Rizwan Ashiq

Posted on June 26, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related