Async JavaScript Cheat Sheet
Understand the event loop, promises, and async/await, then fetch data and cancel work with confidence. Mental models for async code you can trust, whether you or an AI wrote it. You can also download the information as a printable cheat sheet:
Free Bonus: Async JavaScript Cheat Sheet
Get the Async JavaScript Cheat Sheet (PDF), a printable reference to the event loop, promises, async/await, Promise combinators, error handling, fetch, AbortController, and async iteration:
Want a guided path instead of a reference? Start learning at realjs.com.
The Event Loop
- JavaScript runs one call stack at a time
- Microtasks (promise callbacks) run before the next macrotask (timers, I/O)
awaitpauses only its own function
Predict the Order
console.log("1 sync");
setTimeout(() => console.log("4"), 0);
Promise.resolve()
.then(() => console.log("3"));
queueMicrotask(() => console.log("3b"));
console.log("2 sync");
// 1 sync, 2 sync, 3, 3b, 4
Promises
- A promise is pending, then fulfilled or rejected, once
.then()andawaitalways resume asynchronously
Create a Promise
const delay = (ms, value) =>
new Promise((resolve) => {
setTimeout(resolve, ms, value);
});
await delay(5, "done"); // "done"
Resolve From Outside
const { promise, resolve } =
Promise.withResolvers();
setTimeout(resolve, 1, "later");
await promise; // "later"
Sleep in Node.js
import { setTimeout as sleep }
from "node:timers/promises";
await sleep(1000); // Waits 1s
async / await
Await in Sequence or in Parallel
// Sequential: ~2s total
const a = await delay(1000, "a");
const b = await delay(1000, "b");
// Parallel: ~1s total
const [x, y] = await Promise.all([
delay(1000, "x"),
delay(1000, "y"),
]);
Async Functions Return Promises
async function load() {
return 42;
}
load(); // Promise { 42 }
await load(); // 42
Combinators
| Method | Settles when… |
|---|---|
all |
All fulfill, or 1 rejects |
allSettled |
All settle, never rejects |
any |
First fulfills |
race |
First settles |
Collect Every Outcome
await Promise.allSettled([
Promise.resolve(1),
Promise.reject(new Error("x")),
]);
// [{ status: "fulfilled", value: 1 },
// { status: "rejected",
// reason: Error: x }]
First Success Wins
await Promise.any([
Promise.reject(new Error("x")),
delay(1, "ok"),
]); // "ok"
await Promise.race([
delay(10, "slow"),
delay(1, "fast"),
]); // "fast"
Free Bonus: Download the Async JavaScript Cheat Sheet PDF and keep the essentials at hand.
Error Handling
- A rejected promise needs a handler, or Node.js exits
Promise.anyrejects with anAggregateError
try / catch / finally
try {
await Promise.reject(new Error("boom"));
} catch (err) {
console.log(err.message); // boom
} finally {
console.log("cleanup"); // cleanup
}
Chain Handlers
await fetchUser()
.catch((err) => fallback)
.finally(() => spinner.hide());
Catch Unhandled Rejections
process.on("unhandledRejection", (r) => {
console.error("Lost:", r.message);
});
Promise.reject(new Error("oops"));
// Lost: oops
fetch
fetch()rejects on network errors, not on HTTP 404 or 500- Always check
res.okbefore parsing
Fetch JSON Safely
async function getJson(url, signal) {
const res = await fetch(url, { signal });
if (!res.ok) {
throw new Error(`HTTP ${res.status}`);
}
return res.json();
}
await getJson(url); // { id: 1 }
// Missing page: Error: HTTP 404
Fetch Many in Parallel
const users = await Promise.all(
ids.map((id) => getJson(`/u/${id}`)),
);
Cancellation
Time Out a Request
try {
await fetch(url, {
signal: AbortSignal.timeout(3000),
});
} catch (err) {
console.log(err.name); // TimeoutError
}
Abort Manually
const ctrl = new AbortController();
const req = fetch(url, {
signal: ctrl.signal,
});
ctrl.abort();
await req; // AbortError
Combine Signals
const signal = AbortSignal.any([
ctrl.signal,
AbortSignal.timeout(5000),
]);
await getJson(url, signal);
Async Iteration
for awaitconsumes streams and paged APIs one item at a time- Async generators
yieldvalues over time
Write an Async Generator
async function* ticks(n) {
for (let i = 0; i < n; i++) {
await sleep(100);
yield i;
}
}
Consume With for await
for await (const t of ticks(3)) {
console.log(t); // 0, 1, 2
}
Stream a Response Body
const res = await fetch(url);
for await (const chunk of res.body) {
console.log(chunk.length);
}
forEach Ignores await
ids.forEach(async (id) => {
await save(id);
});
console.log("done"); // Logs first
// In order: for (const id of ids)
// await save(id);
await Promise.all( // In parallel
ids.map((id) => save(id)),
);
Want to go deeper on async JavaScript?
RealJS teaches the mental models that let you write, read, and review modern JavaScript with confidence, whether you or an AI wrote it.
Learn more at realjs.com 💡
You can download this information as a printable cheat sheet:
Free Bonus: Async JavaScript Cheat Sheet
Get the Async JavaScript Cheat Sheet (PDF), a printable reference to the event loop, promises, async/await, Promise combinators, error handling, fetch, AbortController, and async iteration: