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! ๐
Hi Cedric,
Nice post.
Just a question.
Can you just clarify on the last bit about async, when you are returning a value using async function, would you just return values as a normal synchronous piece of code? So no callbacks required?
would become
Thanks,
Ben
Hi Ben,
displayData(response.data)
is not the actual code, I just used it to express the meaning.What I normally do is that I return the whole
response
variable, and then where Iโm callinginit()
I would then doresponse.json()
(orresponse.text()
, etc, depending on the nature of the value) to extract the data.Hereโs how it goes:
I hope that helps. Thank you for your input. Based on it I might update the article or write another one.
Cheers