Learning to use JavaScript’s Async Await

Learning to use JavaScript’s Async Await

1_ImJyPIRNLiLXjGSfJQl_dA.png

If you’re familiar with javascript promises, this is the next iteration of that — more succinct and flexible. Async Await is really just syntactical sugar built on top of promises. So why on earth are they that much better if it’s really the same implementation underneath the hood? Well there are quite a few reasons. But first let’s take a look at how to use it.

How We Async/Await

Below we’re going to call a function that makes an API request and returns some data using promises.

const requestData = () => {
  try {
    return apiGetData()
      .then(data => {
        return data
      })
      .catch(err => {
        // Handle error
        console.log(err)
      })
  } catch (err) {
    // Handle error
    console.log(err)
  }

and now let’s try using async/await:

const requestData = async () => {
  try {
    return await apiGetData()
  } catch (err) {
    // Handle error
    console.log(err)
  }
}

As you see, we prepend the function with async , then we use the keyword await before we call a promisified function. In this case, our program will wait for the promisified function to return a value until it proceeds.

Why Async/await is better than using promises

1. Concise

Using the async/await pattern will help to condense the amount of boilerplate code, nesting and chaining you’ve had to do previously. Below is an example of using promises.

const requestData = () =>
  apiGetData()
    .then(data => data)

requestData()

And this is how it looks with async/await:

const requestData = async () => await apiGetData()

requestData()

2. Error Handling

With async/await, error handling becomes much more readable.

const requestData = () => {
  try {
    apiGetData()
      .then(data => {
        return data
      })
      .catch(err => {
        console.log(err)
      })
  } catch (err) {
    console.log(err)
  }

Using the async/await pattern below, the catch block will now handle any parsing errors.

const requestData = async () => {
  try {
    return await apiGetData()
  } catch (err) {
    console.log(err)
  }
}

4. Conditionals

Imagine something like the code below which fetches some data and decides whether it should return that or get more details based on some value in the data.

const requestData = () => {
  return apiGetData()
    .then(data => {
      if (data.needsMoreData) {
        return makeAnotherRequest(data)
          .then(extraData => {
            return extraData
          })
      } else {
        return data
      }
    })
}

This is messy, and sadly this is something you’ll see in your day to day job. But don’t be the person that leaves behind code like this for your colleagues. It’s easy to get lost in nesting, conditionals, braces, and return statements that propagate up the final result.

Now let’s try this again with async/await!

const requestData = async () => {
  const data = await apiGetData()
  if (data.needsMoreData) {
    const extraData = await makeAnotherRequest(data);
    return extraData
  } else {
    return data    
  }
}

Conclusion

There you have it. Async/await should be your go-to over promises or callbacks. As projects grow, readability and cleanliness are one of the most important factors that will help you to reduce tech debt over time.