Skip to main content

Cancelling Work: AbortController

intermediate12 min readLesson 76 of 143

Aborting fetch mid-flight, wiring AbortSignal to timeouts and UI events, and detecting AbortError versus real failures.

Leaving five stale searches running while the user types is a bug: wasted bandwidth, out-of-order responses, race conditions. Cancellation is the fix.

The pieces

AbortController exposes a signal; every consumer of the signal can stop work by calling controller.abort():

const controller = new AbortController();
fetch(url, { signal: controller.signal }).catch(handleAbort);

// later โ€” from a timeout, a new search, or unmount:
controller.abort();

Aborted fetches reject with an AbortError (err.name === "AbortError"). Distinguish it from real errors โ€” the user does not need a scary error box because they typed faster:

function handleAbort(err) {
  if (err.name === "AbortError") return; // expected, ignore
  showError(err);
}

The race-with-timeout idiom

function withTimeout(ms) {
  const c = new AbortController();
  setTimeout(() => c.abort(), ms);
  return c.signal;
}

fetch(url, { signal: withTimeout(5000) });

New searches abort the previous controller โ€” one controller per logical operation, replaced when the operation is replaced. The same signal also stops addEventListener (via { signal }) and can be passed to timers in modern runtimes.

Now practice

Cancellation โ€” PracticeAbort stale work: a search-as-you-type controller, an abortable delay, and an AbortError classifier.3 challenges ยท ยท ~15 min