A Beginner's Guide to Async/Await
Tags: beginners, codenewbie, javascript
Published: 2019-12-15 21:54:05

Async/await was rolled out with ECMAScript 2017, and enables our asynchronous code to flow even more like synchronous code. It's basically syntactic sugar for Promises, so like Promises, it helps us avoid writing deep chains of nested callbacks, and is arguably even more readable than regular Promises.

#### Syntax 

To declare an async function, put `async` at the beginning of your function declaration.

Like so:
```js
async function greeting(word) {
    return word;
}
```
Using the `async` keyword lets the interpreter know that the function should evaluate to a *Promise* instead of directly returning a value. 

So the function above is effectively the same as:
```js
function greeting(word) {
   return Promise.resolve(word);
}
```
In the second function, we are explicitly stating that this function returns a Promise. In the first one, the `async` keyword is doing that implicitly for us.

#### Let's resolve it

Technically, we can call an async function just like a normal Promise, using a `.then()` statement to make sure it evaluates to a value, and not just a Promise object.

```js
async function greeting(word) {
    return word;
}

greeting('Hi'); // Promise { ‘Hi’ } <-- evaluates to a Promise object

greeting('Hey')
.then(word => console.log(word)); // ‘Hey’ <-- evaluates to a fulfilled Promise
```

If we call `greeting` by itself, then it’s going to evaluate to a pending Promise object, so we could use `.then()` to make sure it the Promise is fulfilled.

#### But (a)wait!

What makes an async function so exciting is the possibility of using the `await` keyword. When we put `await` in front of an expression in our async function, we’re telling the interpreter, hey, this expression returns a Promise, so *wait*-- pause code execution here until the function that follows `await` is finished running, and then resolve that Promise!

#### Let's try it out

```js
async function makeCall() {
   try {
      const response = await axios.get('https://somewebsite.com');
      console.log(response.data);
   } catch(error) {
      console.log(error);
   }
};
```

So we’ve got an async function `makeCall()`. Our axios GET request is being called with the `await` keyword, which means that nothing happens with the rest of `makeCall()`  until the response is received from the axios request.

The axios library is also built on Promises-- axios requests return Promises. But if a function does not inherently return a Promise, `await` turns it into one that does.

The `await` keyword basically injects the `resolve` of a Promise that would otherwise need to be finished/fulfilled with a `.then()`.

Here, we’re storing that resolve in a variable because we want to do something with it-- namely, grab the data from that response object and then console log it.

(We handle our errors by placing the body of our main call in a `try` block, and follow that up with a `catch` block.)

Pretty cool! And a bit easier to read than this:
```js
function makeCall() {
    return axios.get('https://somewebsite.com')
        .then((response) => {
        console.log(response)
    }).catch((error) => {
        console.log(error)
    });
}
```

#### Avoid chaining

With normal Promises, when we have multiple Promises that need to be resolved, our code could look something like this:

```js
function makeThreeCalls() {
    return axios.get('https://someurl.com')
    .then(() => {
        axios.get('https://anotherurl.com')
    }).then(() => {
        axios.get('https://yetanotherurl.com')
    }).catch((error) => {
        console.log(error);
    })
}
```

This is definitely better than callback hell. But we're still left with this chain of `.then()`s, and each of those `.then()`s have their own arrow function. 

Using `async/await` makes our code even more readable, especially when multiple calls are involved.
```js
async function makeThreeCalls() {
    const firstCall = await axios.get('https://someurl.com');
    const secondCall = await axios.get('https://anotherurl.com');
    const thirdCall = await axios.get('https://yetanotherurl.com');
    console.log(`${firstCall}, ${secondCall}, ${thirdCall}`)
}
```

This is an async function with three `await` statements in one block of code. It just reads a little more like synchronous code, doesn't it?

We've got three axios requests that are preceded by the `await` keyword, which means they’re going to be resolved Promises. Our interpreter waits for one request to be done before it invokes the next.

#### Promise.all()

We can speed this process up the same way we would with normal Promises. Instead of running the functions one by one, waiting for one function to resolve before we call the next, we can run them in parallel. We do this by calling them with `Promise.all()`.

```js
async function makeThreeCalls() {
    const [ firstCall, secondCall, thirdCall ] = Promise.all([
        await axios.get('https://someurl.com'), 
        await axios.get('https://anotherurl.com'),
        await axios.get('https://yetanotherurl.com')
    ]);
    console.log(`${firstCall}, ${secondCall}, ${thirdCall}`)
}
```
This saves a lot of time.

#### ~~~~

I hope this was a helpful introduction to `async/await`, which is just syntactic sugar on top of Promises. It can make your code even more intuitive and easier to read. It allows us to write asynchronous code that reads more like synchronous code, and helps us avoid the `.then()` chains that are still necessary with normal Promises.