JavaScript Cheatsheet
Async
Use this JavaScript reference while you build software engineering projects, review code, or refresh the syntax you reach for most.
Callbacks
The original async pattern. Still used in Node.js APIs and event listeners.
// Error-first callback convention (Node.js style) fs.readFile("file.txt", "utf8", (err, data) => { if (err) return console.error(err); console.log(data); }); // Simple callback setTimeout(() => console.log("after 1s"), 1000); setInterval(() => console.log("every 1s"), 1000); // Clearing timers const id = setTimeout(fn, 1000); clearTimeout(id); const intervalId = setInterval(fn, 1000); clearInterval(intervalId);
Promises
A Promise is in one of three states: pending, fulfilled, or rejected. Once settled, it never changes state.
// Creating a Promise const p = new Promise((resolve, reject) => { if (success) resolve(value); else reject(new Error("failed")); }); // Consuming p.then(value => console.log(value)) .catch(err => console.error(err)) .finally(() => console.log("done")); // .then can chain — each returns a new Promise fetch("/api/users") .then(res => res.json()) // parse JSON .then(users => users[0]) // extract first .then(user => console.log(user)) .catch(err => console.error(err)); // .then with two callbacks (resolve, reject) p.then( value => console.log("ok", value), err => console.error("err", err) );
Promise Static Methods
// Promise.resolve / reject — wrap value in settled promise Promise.resolve(42) // immediately fulfilled with 42 Promise.reject(new Error()) // immediately rejected // Promise.all — all must resolve; rejects on first rejection Promise.all([p1, p2, p3]) .then(([v1, v2, v3]) => console.log(v1, v2, v3)) .catch(err => console.error("any failed:", err)); // Promise.allSettled (ES2020) — waits for all, never rejects Promise.allSettled([p1, p2, p3]) .then(results => { results.forEach(r => { if (r.status === "fulfilled") console.log("ok:", r.value); else console.error("fail:", r.reason); }); }); // Promise.race — first to settle wins (resolved or rejected) Promise.race([fetch(url1), fetch(url2)]) .then(firstResult => console.log(firstResult)); // Promise.any (ES2021) — first to FULFILL wins; rejects with AggregateError if all reject Promise.any([p1, p2, p3]) .then(firstFulfilled => console.log(firstFulfilled)) .catch(err => console.error(err.errors)); // AggregateError // Timeout pattern with race const withTimeout = (promise, ms) => Promise.race([ promise, new Promise((_, reject) => setTimeout(() => reject(new Error("Timeout")), ms) ), ]);
async / await (ES2017)
async functions always return a Promise. await pauses execution of the async function until the promise settles.
// Basic pattern async function fetchUser(id) { const res = await fetch(`/api/users/${id}`); if (!res.ok) throw new Error(`HTTP error ${res.status}`); return res.json(); // returns Promise<User> } // Arrow function const fetchUser = async (id) => { const res = await fetch(`/api/users/${id}`); return res.json(); }; // Await unwraps the promise value const user = await fetchUser(1); // User object, not Promise<User> // await only works inside async functions // Top-level await is available in ES modules (no function wrapper needed) const data = await fetch("/api").then(r => r.json()); // top-level in modules
Error Handling in async/await
// try/catch async function load() { try { const res = await fetch("/api/data"); const data = await res.json(); return data; } catch (err) { console.error("Failed:", err); return null; } finally { setLoading(false); } } // .catch() on the returned promise load().catch(console.error); // Inline error handling per-await async function safe() { const data = await fetchData().catch(() => null); // null on error if (!data) return; // guard process(data); }
Sequential vs Parallel
// Sequential — each awaits the previous (slower) async function sequential() { const a = await fetchA(); // waits const b = await fetchB(); // waits after a return [a, b]; } // Parallel — fire both, await together (faster) async function parallel() { const [a, b] = await Promise.all([fetchA(), fetchB()]); return [a, b]; } // Start both, await each (parallel but access separately) async function parallel2() { const aPromise = fetchA(); const bPromise = fetchB(); const a = await aPromise; const b = await bPromise; return [a, b]; } // Parallel over array async function fetchAll(ids) { const promises = ids.map(id => fetch(`/api/${id}`).then(r => r.json())); return Promise.all(promises); } // Controlled concurrency (process N at a time) async function batchProcess(items, concurrency = 5) { const results = []; for (let i = 0; i < items.length; i += concurrency) { const batch = items.slice(i, i + concurrency); const batchResults = await Promise.all(batch.map(process)); results.push(...batchResults); } return results; }
fetch API
// GET const res = await fetch("/api/users"); const users = await res.json(); // POST with JSON const res2 = await fetch("/api/users", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name: "Alice", age: 30 }), }); const created = await res2.json(); // Check status if (!res.ok) throw new Error(`${res.status} ${res.statusText}`); // Response methods res.json() // parse body as JSON → Promise<any> res.text() // body as string → Promise<string> res.blob() // body as Blob → Promise<Blob> res.arrayBuffer() // body as ArrayBuffer res.formData() // body as FormData // Response properties res.status // 200, 404, etc. res.statusText // "OK", "Not Found", etc. res.ok // true if status 200–299 res.headers // Headers object res.url // final URL (after redirects) res.redirected // true if redirected // Request options fetch(url, { method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE", headers: { "Authorization": "Bearer token" }, body: JSON.stringify(data) | formData | blob, credentials: "include", // send cookies cross-origin cache: "no-cache", signal: controller.signal, // AbortController mode: "cors" | "no-cors" | "same-origin", redirect: "follow" | "error" | "manual", });
AbortController
const controller = new AbortController(); const { signal } = controller; setTimeout(() => controller.abort(), 5000); // abort after 5s try { const res = await fetch("/api/slow", { signal }); const data = await res.json(); } catch (err) { if (err.name === "AbortError") { console.log("Request aborted"); } else { throw err; } } // Abort multiple requests const ac = new AbortController(); Promise.all([ fetch(url1, { signal: ac.signal }), fetch(url2, { signal: ac.signal }), ]); ac.abort(); // cancels both
Async Iteration (ES2018)
// for await...of — iterate async iterables async function processStream(stream) { for await (const chunk of stream) { process(chunk); } } // Async generators async function* paginate(url) { let page = 1; while (true) { const res = await fetch(`${url}?page=${page}`); const data = await res.json(); if (!data.items.length) break; yield* data.items; page++; } } for await (const item of paginate("/api/items")) { console.log(item); }
Event Loop and Microtasks
// Order: synchronous → microtasks → macrotasks console.log("1 sync"); setTimeout(() => console.log("4 macro"), 0); // macrotask Promise.resolve().then(() => console.log("3 micro")); // microtask queueMicrotask(() => console.log("2 micro")); // microtask // Output: 1, 2, 3, 4 // Resolved promises — microtasks Promise.resolve(42).then(v => console.log(v)); // next microtask checkpoint await Promise.resolve(42); // pause current, queue continuation as microtask
Common Async Patterns
// Retry with backoff async function retry(fn, retries = 3, delay = 1000) { for (let i = 0; i <= retries; i++) { try { return await fn(); } catch (err) { if (i === retries) throw err; await new Promise(r => setTimeout(r, delay * 2 ** i)); } } } // Deferred promise function deferred() { let resolve, reject; const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); return { promise, resolve, reject }; } // Sleep / delay const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); await sleep(1000); // Promise-ify callback API function readFile(path) { return new Promise((resolve, reject) => { fs.readFile(path, "utf8", (err, data) => { if (err) reject(err); else resolve(data); }); }); } // Built-in: util.promisify(fs.readFile)