AbortController in JavaScript: Cancel a Fetch Request
Why you need to cancel
The user types in a search box and the keystrokes fire eight separate fetches. By the time the network responds, only the last one matters β the seven earlier results would overwrite the right one with stale data. Cancel them.
The AbortController API
const controller = new AbortController();
const promise = fetch(url, { signal: controller.signal });
// later, somewhere else
controller.abort();signal is a token. Pass it to fetch. Call controller.abort() and the in-flight request stops; the fetch Promise rejects with a DOMException whose name is "AbortError".
Recognizing abort vs real errors
try {
const r = await fetch(url, { signal });
return r.json();
} catch (err) {
if (err.name === "AbortError") return; // expected, ignore
throw err; // real error, propagate
}Aborts aren't really "errors" from the caller's perspective. Filter them out so they don't end up in error toasts or Sentry.
The replace-on-new-input pattern
let lastController = null;
input.addEventListener("input", async () => {
lastController?.abort();
lastController = new AbortController();
const r = await fetch("/api/search?q=" + input.value, { signal: lastController.signal });
// ... render results
});Every keystroke cancels the previous fetch. Whoever's first to respond IS the latest one. Same trick works for fetch chains in React effects, autocomplete dropdowns, paginated infinite scrolls.
Timeout via AbortSignal.timeout
fetch(url, { signal: AbortSignal.timeout(5000) }); // auto-aborts after 5sShipped in 2023, supported everywhere modern in 2026. Replaces the old "wrap a Promise in Promise.race with a timeout" hack.
Sign up to start coding
Theory is open to everyone. The interactive editor, live preview, and check are unlocked with a 7-day free trial β card required, cancel anytime.
Sign up β free trial βFirst 10 lessons in each track are free. No card needed for those.