async / await, Deeply

What await really pauses, why sequential awaits are often a performance bug, and how errors propagate.

Syntaxasync function f() { const [a, b] = await Promise.all([p1, p2]); }

await does not block the thread -- it suspends the async function, hands control back to the event loop, and resumes when the awaited promise settles. An async function always returns a promise; return x resolves it, throw rejects it.

The sequential-await trap

Awaiting independent tasks one after another makes them run in series for no reason:

const a = await slow();  // 1s
const b = await slow();  // another 1s -- total 2s, wasted

If they do not depend on each other, start them together and await the group with Promise.all -- total time drops to the slowest one.

Error handling

A rejected await throws at the await point, so ordinary try/catch works. An unhandled rejection propagates out as the returned promise's rejection -- always .catch or await the call somewhere.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Abort a stale fetch request using AbortController when the user navigates away before the response arrives.
  • Implement sequential pagination by awaiting each page fetch inside a while loop.
  • Avoid unhandled promise rejections by always pairing every async call with error handling.

More examples

Async iteration over pages

Loops through paginated API pages using sequential awaits, stopping when an empty page is returned.

Example · js
async function fetchAllPages(baseUrl) {
  let page = 1;
  const all = [];
  while (true) {
    const res = await fetch(`${baseUrl}?page=${page}`);
    const data = await res.json();
    if (!data.length) break;
    all.push(...data);
    page++;
  }
  return all;
}

AbortController for cancellation

Passes a signal to fetch and calls abort() to cancel it, triggering an AbortError in the catch.

Example · js
const controller = new AbortController();
const { signal } = controller;
fetch("/api/data", { signal })
  .then(r => r.json())
  .catch(e => console.log(e.name)); // "AbortError"
controller.abort(); // cancel the request

Parallel with error isolation

Wraps Promise.allSettled to return null for any rejected promise instead of throwing.

Example · js
async function safeAll(promises) {
  return Promise.allSettled(promises).then(results =>
    results.map(r => r.status === "fulfilled" ? r.value : null)
  );
}
const data = await safeAll([
  fetch("/api/a").then(r => r.json()),
  Promise.reject(new Error("B down")),
  fetch("/api/c").then(r => r.json())
]);
console.log(data); // [resultA, null, resultC]

Discussion

  • Be the first to comment on this lesson.
async / await, Deeply — JavaScript | SoundsCode