Async/Await in JavaScript
async/await lets you write asynchronous code that looks synchronous by awaiting promises.
Basics
Mark a function async and await promises inside. The return value is wrapped in a promise.
async function fetchValue() {
return 42
}
async function main() {
const v = await fetchValue()
console.log(v)
}
Parallel vs sequential
Awaiting sequentially slows you down; start promises first, then await with Promise.all.
// sequential
const a = await getA()
const b = await getB()
// parallel
const pa = getA()
const pb = getB()
const [a2, b2] = await Promise.all([pa, pb])
Error handling
Use try/catch around awaits or handle with .catch().
try {
const data = await getData()
} catch (e) {
console.error('failed', e)
}
finally for cleanup
const res = await getRes().finally(() => release())
Top-level await
Supported in ESM (modern browsers/Node). Use sparingly to avoid blocking module graphs.
// in a module file
const config = await fetch('/config.json').then(r => r.json())
Timeouts and abort
Combine with AbortController to cancel fetches and with Promise.race for timeouts.
const c = new AbortController()
const p = fetch('/api', { signal: c.signal })
const timeout = new Promise((_, rej) => setTimeout(() => rej(new Error('timeout')), 1000))
const res = await Promise.race([p, timeout])
Pitfalls
- Don’t forget to return/await inside
asyncfunctions (unhandled rejections) - Don’t
awaitinside array.mapwithout collecting promises; usePromise.all - Avoid top-level await inside large module graphs
Summary
- Use
async/awaitfor readable async code - Start work in parallel then await together; handle errors with try/catch
- Support cancellation/timeouts where possible