Understanding async await
It’s fairly simple to dive in and start using straight away but I feel that some people might have missed the core concepts which I think are fundamental to using async await so wanted to write an article detailing these in the terms I understand them.
One common misconception is that async await is an alternative to promises, but this is fundamentally untrue, it’s an accompaniment to promises not a replacement and it’s actually critical to understand promises in depth to make sense of async await, so consider that a prerequisite! Now let’s continue…
What does await do?
Basically it allows you to pause execution (in a non blocking way) until a
resolves, and then act accordingly.
- When used on a
resolves, it will convert the
promiseresolving where you would normally use
.then()to access the returned
await allows a much nicer flatter structure that just looks like synchronous code.
- When used on a
rejects, it will convert that
rejectioninto a thrown that
However, you can also only use the
await keyword inside an
async function, so lets talk about those now…
What does an async function do?
The best way to think of an
async function is that it will always return a promise, even if you don’t actually return one!
- If inside an
asyncfunction a value is returned, externally that will be as if the function returned a
- If inside an
asyncfunction an error is thrown, externally that will be as if the function returned a
This is equivalent to…
Both of these functions will return a
resolves to provide the
.value property of the result from
But what if
rejects instead of
Lets imagine it rejects with the error
As you can see in this example, things are more complex than they appear…
- we have a rejected promise,
- that gets turned into a thrown error,
- that gets turned back into a rejected promise,
- that gets turned back into a thrown error.
But as long as you understand the flow of how
promises are converted to returned
values / thrown
await, and the how returned
values and thrown
errors are converted to
async functions, the flow makes sense.
Async functions are safer too!
One final takeaway is that
async functions are safer, with a lower risk of errors being swallowed. Because if you throw an error anywhere in the code, it will return a rejected promise.
Where as with non
async functions you must be careful. Errors will only be wrapped in a rejected promise if the error is thrown within the
promise chain, but not if it is
thrown before hand. For example….
This function will ensure that if
fetchResults errors we can handle it within our
catch statement. But what would happen if
data wasn’t an object? So the
.page property couldn’t be accessed?
In that case an
error would get
thrown, and because this occurs outside of the
fetchStuff would also throw the
error meaning our catch statement never gets invoked (since no
promise is returned).
async functions this problem goes away.
promise is always returned, if ANY
thrown within this function, it’ll get captured and a
rejected promise is
returned with that
error. It doesn’t have to be part of the
It’s basically giving us this for free…
That’s all for now, hope this helps you better understand