Async/Await in JavaScript
Tags: javascript, programming
Published: 2021-06-21 07:52:00

YOU ARE ALMOST THERE!!! 
<img src="https://media.tenor.com/images/443a2ca263a9b884f9edc415f1ced28a/tenor.gif" alt="wink" />
This will be the last article of the series. 

There are 4 parts in this series:
1. Intro to Asynchronous JS 
2. `Promises` in JavaScript
3. More `Promises` in JavaScript
4. `async`, `await` (this article)

Note: If you are not familiar with the concepts of either callbacks or `Promises`, I highly recommend you to visit the previous articles first. `Promises` and callbacks are the precedents of `async` and `await` and they are the reasons why `async` and `await` exists. 

## Introduction

As mentioned in the previous article, `Promises` were introduced in ES2015 and it were meant to solve the callback hell issues. Turns out `Promises` were not enough. The keywords `async` and `await` were introduced in ES2018 to reduce the boilerplate of `Promises` and to solve the limitation of "don't break the chain" in promises chaining.

Let's see the difference between `Promises` and `async/await`!

A promise:
```javascript
const promise = () => {
  return new Promise(resolve => {
    setTimeout(() => resolve("done!"), 1000);
  })
};
```

`async/await`:
```javascript
const promise = async () => {
  console.log(await promiseAsync());
};
```

OR 

A promise:
```javascript
const promise = () => {
  return Promise.resolve(1);
};
```

`async/await`:
```javascript
const promise = async () => {
  return 1;
};
```

By appending the `async` keyword to any function, the function will return a promise.

## Rewriting a promise with `async` and `await`

Remember how we printed a list of Harry Potter characters from our previous article? Here's the code as a refresher:
```javascript
// grab that main element 
const main = document.getElementById("main");

// fetch the third-party API
// I modified this to just a fetch,
// instead of assigning to a variable
fetch("http://hp-api.herokuapp.com/api/characters")
  .then(response => {
      return response.json();
  })
  .then(characters => {
      main.innerHTML = mapCharacters(characters);
  });

const mapCharacters = (characters) => {
  const names = characters.map(character => `<li>${character.name}</li>`);
  return `<ul>${names}</ul>`
}
```

Let's rewrite this with `aysnc/await`!
1. We'll replace `.then` to `await`
2. We should make the function `async` for them to work!

```javascript
async function fetchCharacters() {
  // read JSON
  let response = await fetch("http://hp-api.herokuapp.com/api/characters");
  let characters = await response.json();

  main.innerHTML = mapCharacters(characters);
};
    
fetchCharacters();

const mapCharacters = (characters) => {
  const names = characters.map(character => `<li>${character.name}</li>`);
  return `<ul>${names}</ul>`
}
```

Now we replace all the `.then` with `await`! It's so much cleaner and less boilerplate!!

And for error handlers, all we have to do is (unfortunately, they don't have the `await` way of doing this to handle error 🥲):
```javascript
fetchCharacters()
  .catch(error => {
    console.log(error)
  });
```
---

## A few things to remember

### 💯 `await` won't work in the top-level code
When we see `await` inside a function, there's an `async` append to the function. However, just a reminder, `await` won't work in the top-level code. In other words, you can't straight up using the `await` keyword on a variable:
```javascript
// this won't work since it's not wrapped
// in an asynchronous function
let response = await fetch("http://hp-api.herokuapp.com/api/characters");
```
We have to wrap `await` inside an asynchronous function.

### 💯 You can catch errors with `try...catch`

One thing I didn't mention earlier in the previous article (and I apologize) is that `Promise.reject(new Error("..."))` is equivalent to `throw new Error("...")`.

With `try...catch`, you can do this:
```javascript
async function fetchCharacters() {
  try {
    let response = await fetch("http://hp-api.herokuapp.com/api/characters");
    let characters = await response.json();

    main.innerHTML = mapCharacters(characters);
  } catch(err) {
    console.log(err);
  }
}
```

### 💯 `async/await` works in `Promise.all` as well!!

If you came from the previous article, you might still be digesting the concept of `Promise.all`. But no worries, we are only going to cover very briefly, so you have an idea.

I am going to use the example from the previous article.
```javascript
const p1 = new Promise((resolve, reject) => {
  setTimeout(() => resolve(console.log(1)), 1000);
});
const p2 = new Promise((resolve, reject) => {
  setTimeout(() => resolve(console.log(2)), 2000);
});
const p3 = new Promise((resolve, reject) => {
  setTimeout(() => resolve(console.log(3)), 3000);
});
const p4 = new Promise((resolve, reject) => {
  setTimeout(() => resolve(console.log(4)), 4000);
});
const p5 = new Promise((resolve, reject) => {
  reject(new Error('reject'));
});

// we wrap the promises in Promise.all and then await
let results = await Promise.all([
  p1, 
  p2, 
  p3, 
  p4, 
  p5
])
```
That's it!!

---

✨ And there you go!! ✨ Now that not only you learned `Promises`, you also learned more about `async/await`! Just remember with `async/await`, `promise.then/catch` is rarely used. `async/await` together provides a great framework to write asynchronous code that is easy to read and write!

---

## Before You Go

Since this is the last article of the series, let's end with a good note by wrapping up what we learned in this series:
- JavaScript is synchronous and single-threaded. Since JS program is typically event-driven, therefore we care about asynchronous programming.
- `Promises` were introduced in ES2015 to solve the callback-hell issue
- The three states of `Promises` are **pending**, **resolved**, **rejected**. 
- When a promise object is **fulfilled**, the result is a value; when a promise object is **rejected**, the result is an error object.
- The three consumer handlers in promise: `.then`, `.catch`, `.finally`
- We can do chain promises with `.then` 
- We can fetch multiple promises with `Promise.all`
- `async` and `await` were introduced in ES2018 to reduce the boilerplate of `Promises` and the limitation of "don't break the chain" of chaining promises.
- When `async/await` is used, `promise.then/catch` is rarely used.

And that's it! I am more than happy if you need to bookmark this series for any refresher in the future!

---

YAY! You made it to the end! Be proud of yourself! And...
<img src="https://i.pinimg.com/originals/b8/e9/d9/b8e9d9d85f988cd021af31a0f37d9fd1.gif" alt="bye gif" />

If there's any mistake or inaccuracy (with the terminology, etc.) in this series, please feel free to comment below. Like a lot of you who are reading this series, I wrote as I learned. 
Hope this series help you build a foundation in asynchronous programming and get rid of the struggle before you read the series! 

---

Last but not least, happy coding!!

<img src="https://blog-c7ff.kxcdn.com/blog/wp-content/uploads/2019/05/IronMan.gif" alt="tony stark and his computer" />

## Resources
🌟 [Modern Asynchronous JavaScript with Async and Await](https://nodejs.dev/learn/modern-asynchronous-javascript-with-async-and-await) (NodeJS documentation)
🌟 [Making asynchronous programming easier with async and await](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await) (MDN)
🌟 [Async/await](https://javascript.info/async-await)
🌟 [JavaScript Async/Await Tutorial – Learn Callbacks, Promises, and Async/Await in JS by Making Ice Cream 🍧🍨🍦](https://www.freecodecamp.org/news/javascript-async-await-tutorial-learn-callbacks-promises-async-await-by-making-icecream/)