Asynchronous JavaScript made readable again: async/await

Published Jun 05, 2017Last updated Nov 20, 2017
Asynchronous JavaScript made readable again: async/await

Being single threaded (at least on the frontend and disregarding the use of web workers) JavaScript makes use of asynchronous execution to keep the interface responsive.

At first we had callbacks (and 'callback hell') then we had promises that help presenting the code better with the separate catch(...) method and also by reducing the need for nesting/indentation.

ES2016 (ES7) provides us with async/await keywords that allow us to write code that seems blocking (synchronous) but is actually waiting (asynchronous).

await vs. .then(function(response) {...})

First let's focus on the await keyword.
Below we make a call that returns a promise and store the resolved value in a const. Then we pass the value to a synchronous method call.

const response  = await service.getData()
displayData(response.data)

Here is how we do it in ES2015 (ES6).

service
  .getData()
    .then(response => displayData(response.data))

With the await syntax the code is more natural to read and the flow is visible at a glance.

With the ES2015 (ES6) version the syntax is different from the synchronous code we write rest of the time. Instead of having one statement after the other, the next line of code has to be wrapped around a function (arrow function here) which will be passed to a chained method call, .then(...).

await explained

When we place the await keyword in front of the call that returns a promise here is what we are ordering the system to do:
Make the call placed right after await and wait for its response. While waiting liberate the thread and perform other operations. When the promise is resolved, come back and store this resolved value in the variable (const in our case). When you are done assigning the variable only then keep executing the next statements synchronously.

code failed

In ES2015 the way to catch errors on a promise is to add a .catch(...) statement that accepts a callback function to which it passes the error.

service
  .getData()
    .then(response => displayData(response.data))
    .catch(error => alertUser(error))

Remember that await make our code look very similar to synchronous code. Thus catching errors is written the same way as with synchronous statements.

try {
  const response  = await service.getData()
  displayData(response.data)
}
catch (error) {
  alertUser(error)
}

async: where do I place it?

The function where that has the await keyword in its statement(s) must be marked async

async function init() {
  const response  = await service.getData()
  displayData(response.data)
}

Readable Asynchronous JavaScript

There you have it: async/await help you write asynchronous code with synchronous look & feel syntax. Asynchronous that is easier to write and easier to reason about.
We write code for other developers, thus I hope this syntax helps you write more understandable code, making your team's life easier.

Let me know if that helps. Suggestions and critiques are most welcome.
Happy coding! 😉

Discover and read more posts from Cedric Poilly
get started
Enjoy this post?

Leave a like and comment for Cedric

11
2