More ES6 magic: Async/Await
Published: 2020-11-09 12:22:24

If you thought `promises` were the best thing since sliced bread after dealing with **callback hell**, wait until you discover the JS magic of `async` and `await`. It's important to note that you must have a general understanding of how promises work in order to truly understand how to use async and await, since they are just *syntactical sugar*. So I'll start with giving a brief overview
of promises to get you up to speed if you've never heard of them, or give you a refresher if you already know what they are.

##*Promises Explained*
<hr>
In the words of MDN
>A promise is an object which can be returned synchronously from an asynchronous function. 

A Promise constructor takes in a function that takes in  two parameters: `Reject` and `Resolve`. It will be in one of 3 possible states:
  1. Resolved: A Promise was successful in retrieving data or getting a value
  2. Rejected: A Promise could not retrieve data due to an error or issue
  3. Pending: not yet Resolved or rejected

A `.then` is then chained to run a function upon success and a `.catch` is added to provide error handling.
```javascript
fetch(url)
  .then(process)
  .then(save)
  .catch(handleErrors)
```
A promise is settled if it’s not pending (it has been resolved or rejected). 

##How does it get any better than that?
Two words: Async & Await. Well, that's actually three, but I digress. 
Let's start with `async`. The async keyword can be placed before a function like `async function test()` or `const test = async() =>{}`. Using the word async before a function means that that function will return a promise. The values returned from that function are automatically wrapped in a resolved promise.
Now onto `await`! Await can **only** be used inside of an async function. You can use async without await but you cannot use await without async. Got it? Good. Await tells javascript to wait, to stop what its doing until the promise returned from the async function is rejected or resolved. Let's take a look at difference.

```javascript
const noAwait = async() =>{
   const {data} = axios.get(url)
console.log(data) // undefined
}
```
This results in undefined being logged to the console. But why? This is because getting requests take time. As you know javascript is synchronus, so it will continue to move along before that promise is resolved and data is provided a value. 

```javascript
const withAwait = async()=>{
  const {data} = await axios.get(url)
console.log(data) // json object
}
```
This results in json being logged to the console. This is because the `await` keyword has been added and tells javascript to wait for the promise to be resolved before it moves on.

You may be thinking: how does error handling work with this syntax? It's very common to use a `try and catch` block for error handling with async and await. 

```javascript
async function f() {

  try {
    let {data} = await axios('http://no-such-url');
  } catch(err) {
    alert(err); // TypeError: failed to fetch
  }
}

f();
```
Since async function do return promises you can also just chain a `.catch` and that will handle a rejected promise as well.

So rather than using promise chaining or the dreaded callback hell nesting, try using async & and await. Together they provide a great framework to write asynchronus code that is easy to read and write.