Day 5 · Concept 14
async / await
async marks a function as promise-returning. await unwraps a promise inline. The code reads like sequential, blocking I/O — but it isn't blocking. The runtime is yielding to other tasks at every await.
1 · The basics
function delay(ms, v) { return new Promise(r => setTimeout(() => r(v), ms)); }
async function run() {
const a = await delay(20, "first");
const b = await delay(20, "second");
return `${a} then ${b}`;
}
run().then(console.log); // "first then second"An async function always returns a promise. The await keyword unwraps the promise when it settles.
2 · Try/catch for errors
async function risky() {
throw new Error("kaboom");
}
async function main() {
try {
await risky();
} catch (err) {
console.log("caught:", err.message);
} finally {
console.log("done");
}
}
main();Replaces .then().catch(). Same semantics, sequential-looking code.
3 · Parallel — don't await in a loop
function delay(ms, v) { return new Promise(r => setTimeout(() => r(v), ms)); }
// Slow — sequential (3 * 50 = 150ms)
async function slow() {
const a = await delay(50, 1);
const b = await delay(50, 2);
const c = await delay(50, 3);
return [a, b, c];
}
// Fast — parallel (~50ms total)
async function fast() {
return Promise.all([delay(50, 1), delay(50, 2), delay(50, 3)]);
}
(async () => {
console.time("slow"); await slow(); console.timeEnd("slow");
console.time("fast"); await fast(); console.timeEnd("fast");
})();4 · Top-level await
// In ES modules (.mjs), await at the top level
const data = await fetch("/api/health").then(r => r.json());
console.log(data);
// In CommonJS, wrap in an IIFE
(async () => {
const data = await someAsync();
console.log(data);
})();5 · Common mistakes
- Awaiting in
forEach.arr.forEach(async x => await ...)doesn't wait. Usefor-ofwithawait, orPromise.all(arr.map(async ...)). - Sequential when parallel works. If calls don't depend on each other, use
Promise.all. - Forgetting that async functions return promises. Calling
run()withoutawaitor.thenfires it but ignores the result and any error. - Mixing async and non-async in chains.
x.then(asyncFn).then(...)— the next.thenreceives the unwrapped value, but be deliberate.
6 · When it clicks
- You reach for
async/awaitover.thenfor most code. Promise.allin an async function is reflex when calls are independent.- You catch unawaited promises in code review.
Found this useful?