JavaScript async and await - in plain English, please
Tags: javascript, codenewbie, beginners, node
Published: 2021-08-20 15:21:12

*If you found this article helpful, you will most likely find my tweets useful too. So here is the [Twitter Link](https://twitter.com/tapasadhikary) to follow me for information about web development and content creation. This article was originally published on my [Blog](https://blog.greenroots.info/).*

<hr />

JavaScript developers love using `async-await`. It is the most straightforward way to deal with asynchronous operations in JavaScript. Suppose we do a poll of usability between the `async/await` syntax vs. the `promise.then()...then().catch()`, async/await going to win with a significant margin. However, we may ignore something important here.

It's not just about the syntax and usability that we need to compare them with. We shouldn't even compare async/await and the plain-old way of handling promises. There are various use-cases and chances that we may use them together. Also, the understanding of promises is the essential part of appreciating the existence of async/await.

> Welcome to the third article of the series, [Demystifying JavaScript Promises - A New Way to Learn](https://blog.greenroots.info/series/javascript-promises). Let's start discussing `async/await`. If you are new to the series, please feel free to check out the previous posts,
- [JavaScript Promises - Explain Like I'm Five](https://blog.greenroots.info/javascript-promises-explain-like-i-am-five)
- [JavaScript Promise Chain - The art of handling promises](https://blog.greenroots.info/javascript-promise-chain-the-art-of-handling-promises)

If you like to learn the async/await keywords from video content as well, this content is also available as a video tutorial here: 🙂

{% youtube CP0CqAkY-Zs %}

*Please feel free to [subscribe](https://www.youtube.com/tapasadhikary?sub_confirmation=1) for the future content*

# The `async/await` are Keywords
JavaScript offers us two keywords, `async` and `await`, to make the usage of promises dramatically easy. The async and await keywords contribute to enhance the JavaScript language syntax than introducing a new programming concept.

In plain English,

- We use `async` to return a promise.
- We use `await` to wait and handle a promise.

Let's expand it further to understand the concepts better.

- The `async` keyword is for a function that is supposed to perform an asynchronous operation. It means the function may be taking a while before it finishes execution, returns a result, or throw an error.

 We use the `async` keyword with a function as,
 
 ```js
 async function fetchUserDetails(userId) {
      // pretend we make an asynchronous call
     // and return the user details
     return {'name': 'Robin', 'likes': ['toys', 'pizzas']};
 }
```
 With the arrow function,

 ```js
 const fetchUserDetails = async (userId) => {
     // pretend we make an asynchronous call
    // and return the user details
    return {'name': 'Robin', 'likes': ['toys', 'pizzas']};
 }
 ```
 So, what does the async function `fetchUserDetails` returns when we invoke it? It returns a `Promise`.

 ![async-retuns.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1628998752221/39MQFzai6.png?border=1,CCCCCC&auto=compress)

 The difference between a regular function and an `async function` is, the latter always returns a promise. If you do not return a promise explicitly from an async function, JavaScript automatically wraps the value in a Promise and returns it.

- The `await` keyword is for making the JavaScript function execution wait until a promise is settled(either resolved or rejected) and value/error is returned/thrown. As the  `fetchUserDetails` async function returns a promise, let us handle it using the `await` keyword.

 ```js
 const user = await fetchUserDetails();
 console.log(user)
 ```
 Now, you will see the returned user object in the console log,

 ![await-result](https://cdn.hashnode.com/res/hashnode/image/upload/v1628942424595/jBSJQqQBU.png?border=1,CCCCCC&auto=compress)

 You would have used the plain-old `.then()` method to handle that promise without the `await` keyword.

 ```js
 fetchUserDetails().then((user) => console.log(user));
 ```

# A Few Rules about using `async/await`
We need to understand a few simple rules to use the async and await keywords.

- You can not use the `await` keyword in a regular, non-async function. JavaScript engine will throw a syntax error if you try doing so.

 ```js
 function caller() {
   // Using await in a non-async function.
   const user = await fetchUserDetails();
 }

 // This will result in an syntax error
 caller();
 ```
- The function you use after the `await` keyword may or may not be an `async` function. There is no mandatory rule that it has to be an async function. Let's understand it with the following examples,

 Create a non-async function that returns the synchronous message, say, `Hi`.

 ```js
 function getSynchronousHi() {
    return 'Hi';
 }
 ```
 You can still use the keyword `await` while invoking the above function.

 ```js
 async function caller() {
    const messageHi = await getSynchronousHi();
    console.log( messageHi);
 }

 caller(); // Output, 'Hi' in the console.
 ```
 As you see, we can use the `await` *with a non-async function* but, we *can not use it within(or inside) a non-async function*.

- The [V8 engine(version >= 8.9) supports the top-level await](https://v8.dev/features/top-level-await) in modules. It means you are allowed to use it outside of an async function. The Chrome DevTools, Node.js REPL support the top-level await for a while now. However, it is still not supported beyond the environments we just discussed.

 To use the top-level `await` in a non-supported environment, the solution is to wrap it into an anonymous function, like this,

 ```js
 (async () => {
     const user = await fetchUserDetails();
 })();
 ``` 

# How to Handle Errors with `async/await`?
We learned about error handling using the `.catch()` handler method in the [promise chain](https://blog.greenroots.info/javascript-promise-chain-the-art-of-handling-promises) article. If the promise rejects, it throws the error, and we need to catch it to handle it.

With the `async/await` keywords, we can handle the error with traditional `try...catch`. When there is an error, the control goes to the catch block. Please have a look at the example below. 

Assume we have a function that validates if the `userId` and `password` are blank. If so, throw an error by rejecting the promise. Otherwise, resolve it with a success message. 

```js
const validateUser = ({userId, password}) => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if (userId && password) {
                resolve(`${userId} you have been authenticated successfully!!!`);
            } else {
                reject({message: 'userId or Password could be blank!'});
            }

        }, 2000);
    });
}
```
As the above method returns a promise, we can handle it using the `await` keyword. Let us focus on the case where we pass the userId and password as empty strings.

```js
const app = async () => {
    const data = {
        userId: '',
        password: ''
    };

    try {
        console.log('Initializing...');
        const result = await validateUser(data);
        console.log(result);
    } catch (e) {
        console.error(e.message);
    }
}

// invoke the function app
app();
```
When we invoke the `app()` function, the `validateUser(data)` will throw an error implicitly. We handle it using the `try...catch` in the `app()` function. The control will go to the `catch` block. We will get the error log as,

![error-catch.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1628993450062/mwxn3VrO8.png?border=1,CCCCCC&auto=compress)

If we pass valid `userId` and `password` values, we will see the expected result log in the console.

# Can We Write the `PizzaHub` example with `async/await`?
Surely, I think that's a great idea. We have created APIs and the methods to handle the pizza order in the [Robin and the PizzaHub Story](https://blog.greenroots.info/javascript-promise-chain-the-art-of-handling-promises). Remember the `orderPizza()` function? We [handled the promises](https://github.com/atapas/promise-interview-ready/blob/b479dc376ac9dd02a637a134dbd9c7af1b571614/src/02-promise-chain/02-promise-chain-pizza.js#L107) using the `.then()` and `.catch()` handler methods.

Let's rewrite the `orderPizza()` function using `async/await`. You bet, it is a much simplified version as we see below,

```js
async function orderPizza(type, name) {
    try{
        // Get the Nearby Pizza Shop
        const shopId = await fetch("/api/pizzahub/shop", {
            'lang': 38.8951 , 
            'lat': -77.0364});
        // Get all pizzas from the shop  
        const allPizzas = await fetch("/api/pizzahub/pizza", {
            'shopId': shopId});
        // Check the availability of the selected pizza
        const pizza = await getMyPizza(allPizzas, type, name);
        // Check the availability of the selected beverage
        const beverage =  await fetch("/api/pizzahub/beverages", {
            'pizzaId': pizza.id});
        // Create the order
        const result = await create("/api/order", {
                beverage: beverage.name,
                name: name,
                type: type,
            });
        console.log(result.message);
    } catch(error){
        console.error(error.message);
    };
}
```
Please find the [complete source code from here](https://github.com/atapas/promise-interview-ready/blob/main/src/03-async-await/03-async-await-pizza-hub.js). So now you know how to write the `orderPizza()` function using both the async/await and plain-old promises respectively. 

Do you want to guess or try how it would look using the JavaScript `callback` functions? Please take a [look from here](https://github.com/atapas/promise-interview-ready/blob/main/src/02-promise-chain/02-callback-hell.js). I hope you appreciate the world of promises and async/await a lot more now 😀.

# So, What's Next?
Thank you for your effort to learn and master JavaScript Promises. It is indeed an essential aspect of the language. Up next, we will learn about `Promise APIs`. `Promise APIs` and the `async/await` keywords make it a much better experience in handling promises. We will learn about it using visual demonstrations and examples.  

Until then, please enjoy learning and stay motivated. You can find all the source code used in this article from this Github repo,

{% github atapas/promise-interview-ready no-readme %}

<hr />

I hope you enjoyed this article or found it helpful. Let's connect. Please find me on [Twitter(@tapasadhikary)](https://twitter.com/tapasadhikary), sharing thoughts, tips, and code practices. Would you please give a follow?