Async Await: 60% of the time, it works every time
Tags: javascript, promises, async, await
Published: 2019-04-27 20:39:24

---
title: Async Await: 60% of the time, it works every time
published: true
description: When to use simple promise methods, and when async await is a great fit!
tags: js, promises, async, await
---

## All aboard the hype train.

Hot take: __async await__ isn't great for everything.

When I saw people writing this:

```js
const printF = async () => {
  try {
    const a = await getA()
    const b = await getB(a)
    const c = await getC(b)
    const d = await getD(c)
    const e = await getE(d)
    const f = await getF(e)
    console.log(f)
  } catch (err) {
    console.error(err)
  }
}
```

as a replacement for this:

```js
const printF = () =>
  getA()
   .then(getB)
   .then(getC)
   .then(getD)
   .then(getE)
   .then(getF)
   .then(console.log)
   .catch(console.error)
```

I thought it was a big step in the wrong direction. It added a bunch of boilerplate for little benefit. I had try-catch for years, I didn't wanna go back!

I had some serious questions for my friends at work who were only using async await:

![Brick are you just looking at things in the office and saying that you love them?](https://media.giphy.com/media/VnK6iD9Xj9Sww/giphy.gif)

> Do we _really_ love async await, or are we just saying that because we saw it?

![I love lamp.](https://media.giphy.com/media/2oNyZo0GZXfgI/giphy.gif)


## When to love lamp.

The example above was actually pretty atypical. It was just to point out that we don't need async/await for _everything_.

It's not always "more readable", it just looks more like synchronous code.

In reality, people don't pay me to `printF`. Instead, I build websites for a living, which is secretly just turning strings into other strings.

So when I get this string:

```js
'https://www.<some-website>.com/people/ryan'
```

I turn it into this string:

```html
<div>
  <h1>Ryan Haskell-Glatz</h1>
  <section>
    <h3>Posts</h3>
    <ul>
      <li>Elm is neat.</li>
      <li>Promises are neat.</li>
      <li>Saying neat is neat.</li>
    </ul>
  </section>
</div>
```

But sometimes my strings are in a database:

```js
// MongoDB
{
  people: [
    { _id: 1, slug: 'ryan', name: 'Ryan Haskell-Glatz' },
    // ... more people
  ],
  posts: [
    { _id: 12, slug: 'elm-is-neat', title: 'Elm is neat.', author: 1 },
    { _id: 13, slug: 'promises-are-neat', title: 'Promises are neat.', author: 1 },
    { _id: 14, slug: 'saying-neat-is-neat', title: 'Saying neat is neat.', author: 1 },
    // ... more posts
  ]
}
```

So my Javascript functions look more like this:

```js
const mongoose = require('mongoose')

const getPosts = (person) =>
  mongoose.model('posts')
    .find({ author: person })
    .select('title')
    .lean()
    .exec()

const getPerson = (slug) =>
  mongoose.model('people')
    .findOne({ slug })
    .select('name')
    .lean()
    .exec()
    .then(person => person || Promise.reject(`Couldn't find a person with slug: ${slug}`))

const getPeopleDetailPage = (req) =>
  getPerson(req.params.slug)
    .then(person =>
      getPosts(person)
        .then(posts => ({ person, posts }))
    )
```

### Making things nicer

Both `getPosts` and `getPerson` are fine, async await wouldn't improve anything.

Notice how I nested my `.then` functions in `getPeopleDetailPage`? Kinda looks like that pointy triangle callback hell stuff.

The reason I nested things was because I needed access to __both__ `person` and `posts` to return them back as an object.

Let's rewrite the last function:

```js
const getPeopleDetailPage = async (req) => {
  const person = await getPerson(req.params.slug)
  const posts = await getPosts(person)

  return { person, posts }
}
```

Here, person and posts are both in scope, so I don't need to nest things.

Async await is great for functions that combine other promises together. It helps us keep things in scope so we don't have to forget `)` and indent 47 times!

Maybe it is better than promises...

![60% of the time, it works every time](https://media.giphy.com/media/k5lj4s1qxaSyI/giphy.gif)

## Upgrading things later

Let's say a new collection called "tags" shows up, and we want to include Ryan's tags on his detail page.

Here's the new database:

```js
// MongoDB
{
  people: [
    { _id: 1, slug: 'ryan', name: 'Ryan Haskell-Glatz' },
    // ... more people
  ],
  posts: [
    { _id: 12, slug: 'elm-is-neat', title: 'Elm is neat.', author: 1 },
    { _id: 13, slug: 'promises-are-neat', title: 'Promises are neat.', author: 1 },
    { _id: 14, slug: 'saying-neat-is-neat', title: 'Saying neat is neat.', author: 1 },
    // ... more posts
  ],
  tags: [
    { _id: 25, name: 'js', people: [ 1 ] },
    { _id: 26, name: 'elm', people: [ 1, 2 ] },
    { _id: 27, name: 'web', people: [ 1, 5 ] },
    // ... more tags
  ]
}
```

And our new `getTags` function:

```js
const getTags = (person) =>
  mongoose.model('tags')
    .find({ people: person })
    .select('name')
    .lean()
    .exec()
```

We can update our function with `Promise.all` to do some great stuff:

```js
const getPeopleDetailPage = async (req) => {
  const person = await getPerson(req.params.slug)
  const [ posts, tags ] = await Promise.all([
    getPosts(person),
    getTags(person)
  ])

  return { person, posts, tags }
}
```

Using `Promise.all` will handle doing things in parallel, so we get the awesome performance and error handling benefits.

## Handling Errors

Outside of this function, our users can decide how they want to handle errors.

If this was an API endpoint with ExpressJS, this is what that might look like:

```js
const express = require('express')
const app = express()

app.get('/api/people/:slug', (req, res, next) =>
  getPeopleDetailPage(req)
    .then(data => res.json(data))
    .catch(err => next(err))
)
```

Notice I used async/await without try-catch, hooray!

![I'm not even mad. That's amazing.](https://media.giphy.com/media/mmw01I9sFtfi/giphy.gif)

## That's it!

Hope you enjoyed reading, I'm glad I finally came around to using async await, and I wanted to share the benefit of using it.

It's not a silver bullet for everything, but it works great with Promises.

> __Async await__: 60% of the time, it works every time.

![That doesn't make sense.](https://media.giphy.com/media/8xggx6JIPHdWE/giphy.gif)