Javascript's async and await - what problem do they solve?
Asynchronous code is one of Javascript's most powerful features and one of its hardest to manage pain points. We've come a long way, from callback functions through endless third-party promise implementations to a full first-class citizen Promise
in ES2015:
doAsyncThing(function (err, res) {
if (!!err) {
// Handle the error
}
doAnotherAsyncThing(res + 1, function (err, res) {
if (!!err) {
// Handle the error
}
// and so on into callback hell...
})
})
doAsyncThing()
.then(function (res) {
return doAnotherAsyncThing(res + 1)
})
.then // ...
Arrow functions go some way toward making that promise code even easier to read and write:
doAsyncThing()
.then(res => doAnotherAsyncThing(res + 1))
.then // ...
But it's still not quite there. It's still not as easy as synchronous code is.
What's the problem?
Consider the following bit of completely normal synchronous Javascript:
function getRawData() {
return 100
}
function getDoubledData() {
const data = getRawData()
console.log(data)
return data * 2
}
Simple, yes? But what if suddenly that data
needs to come from an API? Well, with promises you might end up with something along this pattern:
function getRawData() {
return Promise.resolve(100)
}
function getDoubledData() {
return (
getRawData()
.then(data => {
console.log(data)
return data
})
.then(data => data * 2)
)
}
It's arguably about as clean, but it's also completely different. The structure of getDoubledData()
is fundamentally changed. There is no longer a variable assignment, an couple of anonymous functions have appeared, and most importantly the way you consume getRawData()
has changed entirely. This could easily be much more of a pain point if your code had any real complexity to it.
async and await
Enter the two hottest new Javascript keywords on the block. These two little words let you write code that looks near-as-damnit the same as synchronous code with all the power of Javascript's ability to Go Do Other Things While You Wait built in.
Let me show you what we can do with async
and await
:
async function getRawData() {
return Promise.resolve(100)
}
async function getDoubledData() {
const data = await getRawData()
console.log(data)
return data * 2
}
You guys.
This is literally the exact same code as the synchronous example, but with three little keywords added. No re-architecting has happened - getRawData()
is still consumed in the exact same way.
This kind of example isn't contrived, either - the pattern comes up all the time in real programming: previously nice synchronous code suddenly needs an API call or to take user input, and half your app needs re-structuring.
async
and await
bring us much closer to the dream of being able to simply make that change in place. In the near future I'll talk more about the ins and outs of their usage and the features we can expect from them.
When can I have it?! I WANT IT NOW
Well, hold your horses, a bit. Or don't. It depends, just like it always does with new JS features.
The proposal for asynchronous functions (which introduces async
and await
) didn't make it far along enough the great TC39 conveyer belt of Cool New Stuff in time to get into ES2015, but it has now been included in enough browsers that it's a Stage 4 Proposal, which is to say a Finished Proposal. It's therefore included in the latest draft of the language spec.
Chrome 55 will support them out of the box:
📝 Async functions are enabled by default in Chrome 55. Here's how they work, and why I love them: https://t.co/cuvjBu7Jvi pic.twitter.com/b5uCOZNUIN
- Jake Archibald (@jaffathecake) October 20, 2016
and you can as always use Babel, which supports them too. Check out their sandbox to play with it online! Here's the above code to get you started.
await asynchronousFunctions()
haveFun(`🙋`)
Originally on unwttng.com.
Jake Archibald tweeted @ 20 Oct 2016 - 08:12 UTC
Disclaimer: I am just a bot trying to be helpful.