Introduction
async/await is syntax on top of promises for writing asynchronous code
that reads like synchronous code.
- async function (developer.mozilla.org)
- await (developer.mozilla.org)
async and await
async function load() {
const res = await fetch('/data.json')
return res.json()
}
load() // → Promise
try {
const data = await load()
} catch (err) {
console.error(err) // rejection lands here
}
An async function always returns a promise; await unwraps it. return
resolves, a throw rejects, and top-level await works in ES modules only.
See: async function, await (developer.mozilla.org)
Running in parallel
// Sequential: one after another
for (const id of ids) {
results.push(await getItem(id))
}
// Parallel: start all, then await all
const results = await Promise.all(ids.map(getItem))
| Call | Resolves when |
|---|---|
Promise.all() | all fulfill, else rejects |
Promise.allSettled() | every one settles |
Promise.any() | first one fulfills |
Promise.race() | first one settles |
Awaiting in a loop is sequential; map plus Promise.all starts all at once.
Promise.all() fails fast; Promise.any() throws AggregateError if every
input rejects.
See: Promise.all(), Promise.allSettled(), Promise.any() (developer.mozilla.org)
Timers
setTimeout()
const id = setTimeout(() => {
console.log('later')
}, 1000)
clearTimeout(id)
setInterval()
const id = setInterval(() => {
console.log('tick')
}, 1000)
clearInterval(id)
sleep()
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
await sleep(1000)
setTimeout() runs once; setInterval() repeats until cleared. sleep()
wraps a timer in a promise so it can be awaited.
See: setTimeout(), setInterval(), clearTimeout() (developer.mozilla.org)
Cancellation
const controller = new AbortController()
fetch('/data.json', { signal: controller.signal })
.catch(err => console.error(err.name))
controller.abort()
// Built-in timeout signal
const signal = AbortSignal.timeout(5000)
await fetch('/data.json', { signal })
Pass signal to fetch() and call abort() to cancel a request. A manual
abort rejects with AbortError; a timeout rejects with TimeoutError.
See: AbortController, AbortSignal.timeout() (developer.mozilla.org)
Pitfalls
load() // floating promise, unhandled
items.forEach(async item => {
await save(item) // forEach ignores this
})
for (const item of items) {
await save(item) // sequential, one at a time
}
Missing await leaves a floating promise, so rejections go unhandled;
forEach() ignores its async callback; awaiting in a loop is sequential
(fine for rate limits).
See: async function, await (developer.mozilla.org)
0 Comments for this cheatsheet. Write yours!