Just like we have Promises to add some syntactic sugar to structured callbacks, we now have async functions that come with ES7 to help us write cleaner code when working with promises and asynchronous operations.
- The
async
keyword is required - Async functions return a
Promise
- An async function can contain an
await
expression- Using the
await
expression will pause the execution of the function and await resolution of the specific promise it is called on
- Using the
Take the following example which compares a bit of a contrived problem using promises vs. async/await.
First assume we have these functions written:
const wait2Seconds = value => {
return new Promise(resolve => {
setTimeout(() => {
resolve(value);
}, 2000);
});
}
const wait4Seconds = value => {
return new Promise(resolve => {
setTimeout(() => {
resolve(value);
}, 4000);
});
}
Next we have a function that takes a 3rd value, chains promises to wait until we have the values from the first two timeout functions and returns a promise with all of them added up. Writing this using promises can become overwhelming quickly.
const addStuff = value => {
const promiseToReturn = wait2Seconds(10)
.then(val => {
return val
})
.then(val1 => {
return wait4Seconds(20)
.then(val2 => {
return val2 + val1
})
.then(sum => {
return sum + value
})
})
return new Promise(res => res(promiseToReturn))
}
Let's see what it looks like using async and await:
const addStuff = async value => {
const val1 = await wait2Seconds(10)
const val2 = await wait4Seconds(20)
return value + val1 + val2
}
MUCH more readable :).
But, it matters where we say to await
the resolution of a promise. Take the following:
const addStuff = async value => {
const val1 = wait2Seconds(10)
const val2 = wait4Seconds(20)
return value + await val1 + await val2
}
Instead of awaiting the first promise, and then the second, this code fires off both and essentially takes as long as the longest timeout. This is more like using Promise.all
:
const addStuff = value => {
const promisesToResolve = [
wait4Seconds(10),
wait2Seconds(20)
]
return Promise.all(promisesToResolve).then(vals => {
return value + vals.reduce((acc, val) => acc + val, 0)
})
}
This example takes only as long as the longest setTimeout because it fires off the wait2Seconds
and wait4Seconds
back to back. Let's throw some console.logs in our timed functions to see how these differ.
My guess is you're still shaking your head wondering wtf is going on. That's ok!
Check out this article!
- What is an async function?
- Why were they added to the ECMAScript standard?
- What does an async function return?
- What does the
await
keyword do within an async function?