JavaScript Cheatsheet
Async
Use this JavaScript reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.
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)