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)