async / await Refresher
async/await is syntactic sugar over promises that lets you write asynchronous code that reads like synchronous code — top to bottom, with normal try/catch error handling. It is the dominant style in modern Node.js. Critically, it does not replace promises — every async function returns one, and await only knows how to wait on them.
The two keywords
asyncbefore a function makes it always return a promise — a returned value is auto-wrapped, a thrown error becomes a rejection.awaitpauses only the current async function until a promise settles, then yields its value (or throws its rejection). The event loop keeps serving everyone else meanwhile.
async function getUser(id) {
const res = await fetch(`/api/users/${id}`) // pause until response
const user = await res.json() // pause until parsed
return user // wrapped in a promise
}
const user = await getUser(1)Error handling with try/catch
A rejected awaited promise throws at the await, so you handle it with ordinary try/catch/finally — the thing callbacks could never do:
async function loadConfig() {
try {
const data = await readFile('config.json', 'utf8')
return JSON.parse(data)
} catch (err) {
console.error('Could not load config:', err.message)
return {} // sensible fallback
} finally {
console.log('load attempt finished')
}
}Sequential vs parallel — a costly mistake
Slow — 3x the latency (each waits for the previous)
const a = await fetchA() // wait 100ms... const b = await fetchB() // then wait 100ms... const c = await fetchC() // then wait 100ms... → ~300ms total
Fast — all in flight at once
const [a, b, c] = await Promise.all([fetchA(), fetchB(), fetchC()]) // → ~100ms total
Iterating async work properly
// Parallel — all at once (watch out for rate limits / memory)
await Promise.all(ids.map((id) => processItem(id)))
// Strictly in order — when each must finish before the next
for (const id of ids) {
await processItem(id)
}Top-level await
In ES modules you can await at the top level of a file without an async wrapper — handy for setup and configuration. It is not available in CommonJS:
setup.mjs
const config = await loadConfig()
const db = await connectToDatabase(config.dbUrl)
export { db }How it maps to promises
async/await | Promise equivalent |
|---|---|
|
|
|
|
|
|
|
|
|
|