Under The Hood
frontend javascript DOM spec (AbortController/AbortSignal), fetch

AbortController & AbortSignal: Cascading Fetch/Listener Cleanup

Last updated
Prerequisites:
fetch and async/await basics
Understanding of event listeners and cleanup
  • abort-controller
  • abort-signal
  • fetch
  • cleanup
  • cancellation
  • events

Read at your depth

The practical view

AbortController lets you cancel fetch requests and other async work. const ac = new AbortController(); fetch(url, { signal: ac.signal }); // later: ac.abort();. Aborting rejects the fetch with an AbortError (name === 'AbortError'), and you catch it to distinguish cancellation from real failures. The signal is also an EventTarget: signal.addEventListener('abort', handler) lets other work react. You can pass the same signal to multiple fetches, so one abort cancels them all. Always clean up: remove the listener or call controller.abort() in teardown to avoid leaks in components that unmount mid-request.

The same idea in other frameworks

react equivalent
React effects commonly create an AbortController per effect and abort() in cleanup to cancel in-flight fetches on unmount.

Legacy vs modern

Ignoring cancellation vs aborting in teardown

An unmanaged fetch continues after unmount and can set state on a dead component; aborting in cleanup cancels the request and prevents state races.

before → after
Fetch without abort on unmount
fetch(url).then(setState); // ❌ OLD: no signal — keeps running after unmount, may setState on a removed component
AbortController cleanup
const ac = new AbortController();
const res = await fetch(url, { signal: ac.signal }); // ✅ NEW: wired in
ac.abort(); // cancels the request; rejects with AbortError

Interview gotchas

Context

This probes the cancellation mechanics — that abort rejects with a specific error type and triggers network teardown — which is central to correct async UI code.

The mechanical answer

Calling abort() sets the signal's aborted flag, stores the abort reason, and synchronously dispatches the abort event. The fetch operation observes the signal; its promise rejects with a DOMException whose name is 'AbortError' (the stored reason) rather than a network/HTTP error. The underlying network request is torn down — the connection is cancelled and any streaming response is aborted. To distinguish cancellation from failures, check err.name === 'AbortError' (or err === signal.reason) and rethrow otherwise. Because the rejection is a DOMException, unhandled abort rejections still surface as unhandled rejections if you forget the catch.

Trap

The naive answer is 'abort just makes fetch return undefined'. It rejects the promise, and uncaught abort rejections cause unhandled-rejection errors. Another trap: catching the error and treating AbortError like a server error — cancellation is expected control flow, not a failure, so it must be filtered. Candidates who check the error name and rethrow non-abort errors show production-ready async handling.

Under The Hood — a multi-depth technical interview hub.

Third-party licenses Press ⌘ K to search.