Cancel Request
Prompt
Write JavaScript code that demonstrates how to cancel an in-flight Fetch API request based on user interaction.
- Use the Fetch API to make a network request when the "Fetch" button is clicked
- Cancel the in-flight request when the "Cancel" button is clicked
- Log appropriate messages for both successful fetches and aborted requests
Note
You may want to slow down API responses in the browser for testing. Open Chrome DevTools (F12), click the Network tab, and change the dropdown from "No throttling" to Slow 3G or Fast 3G. This simulates a slow connection so you have time to hit Cancel before the response arrives.
Playground
Look into the AbortController Web API. It was specifically designed to cancel fetch requests. You create a controller, pass its signal to the fetch call, and call controller.abort() to cancel.
You'll need to create a new AbortController each time the Fetch button is clicked, because controllers are single-use. Store it in a variable that the Cancel button's handler can access.
When abort() is called, the fetch() promise rejects with a DOMException whose name is "AbortError". You can catch that in your .catch() block to distinguish aborts from real network errors.
Solution
Explanation
This question tests whether you know about AbortController, which is the standard way to cancel fetch requests in modern JavaScript. It comes up in interviews because it touches on a very real problem: users clicking away, navigating to a different page, or explicitly canceling an action while a network request is still in flight.
The key player here is AbortController. When you create one, it gives you a signal object. You pass that signal into the fetch call's options, and from that point on the controller and the fetch request are linked. Calling controller.abort() tells the browser to cancel the underlying network request.
controller = new AbortController();
const signal = controller.signal;
fetch(URL, { signal });One important detail that trips people up: you need to create a new AbortController for every fetch request. Controllers are single-use. If you reuse one that's already been aborted, any fetch tied to it will reject immediately. That's why we assign a fresh controller inside fetchDogs rather than creating one globally.
The variable controller is declared in the outer scope so both the fetch handler and the cancel handler can access it. The cancel handler checks if controller exists before calling abort() to avoid errors when Cancel is clicked without an active request.
When abort() is called, the fetch() promise rejects with a DOMException named "AbortError". This ends up in the .catch() block alongside genuine network errors. In a production app, you'd typically check err.name === 'AbortError' to distinguish user-initiated cancellations from real failures and handle them differently (for instance, you probably don't want to show an error toast when the user intentionally canceled).
AbortController beyond fetch
AbortController isn't limited to fetch requests. You can pass its signal to addEventListener to auto-remove event listeners, to ReadableStream operations, or to any custom async workflow that accepts an AbortSignal. It's a general-purpose cancellation mechanism.
More about AbortController on MDN