Link copied!
Canceling Fetch API Requests in JavaScript with AbortController Technical Log

TechiesAIE Journal

Canceling Fetch API Requests in JavaScript with AbortController

TechiesAIE
TechiesAIE
Lead Developer · TechiesAIE
4 min read 665 words

Based on the sources linked below.

Cover image: Aboutbigdata · CC BY-SA 4.0 · License · Image source

To cancel an ongoing Fetch API request in JavaScript, you utilize the AbortController interface. This object provides a signal that can be associated with a fetch request, allowing you to programmatically terminate the operation before it completes. When a request is aborted, the promise returned by fetch() rejects with an AbortError exception.

How AbortController Works

The AbortController works by creating an `AbortSignal` object, which acts as a communication channel. This signal is then passed into the options object of a fetch() request. When the AbortController's `abort()` method is called, it triggers the associated signal, causing any fetch requests linked to that signal to be canceled.

This mechanism is crucial for managing network requests, especially in single-page applications where users might navigate away or trigger new requests before previous ones finish. Canceling unneeded requests can improve performance and prevent race conditions.

Steps to Cancel a Fetch Request

1. Create an AbortController Instance

First, instantiate a new AbortController object. This controller will manage the signal for your request.

const controller = new AbortController();

2. Associate the Signal with the Fetch Request

When making your fetch() call, include an options object and assign `controller.signal` to the `signal` property. This links your fetch request to the controller.

async function fetchData() { try { console.log("Starting fetch"); const response = await fetch("https://example.org/get", { signal: controller.signal, }); console.log(`Response: ${response.status}`); } catch (e) { if (e.name === 'AbortError') { console.error("Fetch aborted:", e.message); } else { console.error("Fetch error:", e.message); } } }

3. Call abort() to Cancel the Request

To cancel the request, simply call the `abort()` method on your `AbortController` instance. This will cause the `fetch()` promise to reject.

controller.abort(); console.log("Canceled fetch");

Practical Example

Consider a scenario where a user can initiate a data fetch, but also has a button to cancel it. The following code demonstrates this setup:

const controller = new AbortController(); const fetchButton = document.querySelector("#fetch"); const cancelButton = document.querySelector("#cancel"); fetchButton.addEventListener("click", async () => { try { console.log("Starting fetch"); const response = await fetch("https://example.org/get", { signal: controller.signal, }); console.log(`Response: ${response.status}`); } catch (e) { console.error(`Error: ${e}`); } }); cancelButton.addEventListener("click", () => { controller.abort(); console.log("Canceled fetch"); });

In this example, clicking the 'fetch' button starts the request. If the 'cancel' button is clicked before the fetch completes, `controller.abort()` is called, and the `fetch()` promise will reject with an `AbortError`. This allows your application to handle the cancellation gracefully, for instance, by stopping a loading indicator or displaying a message.

Handling Response Body Reading After Abort

It's important to note that if a request is aborted after `fetch()` has been fulfilled (meaning headers and status are received) but before the response body has been fully read, attempts to read the response body (e.g., `response.json()`, `response.text()`) will also reject with an `AbortError` exception. This means your error handling should anticipate this possibility when processing response bodies.

async function getAndAbortBody() { const controller = new AbortController(); const request = new Request("https://example.org/get", { signal: controller.signal }); try { const response = await fetch(request); controller.abort(); // Abort after headers received but before body read const text = await response.text(); // This line will throw AbortError console.log(text); } catch (e) { if (e.name === 'AbortError') { console.error("Body read aborted:", e.message); } else { console.error("Other error:", e.message); } } }

Limitations and Considerations

The AbortController is widely supported in modern browsers and Web Workers. However, it's a client-side mechanism. While it stops the browser from processing the response and resolves the promise, it does not necessarily stop the request from reaching the server or the server from processing it. The server might still complete the operation, even if the client has abandoned it. This is a crucial distinction for operations that have side effects on the server, such as data updates or deletions.

It's also worth noting that `AbortController` objects are single-use for a specific cancellation. If you need to make another fetch request that can be canceled, you should create a new `AbortController` instance for that specific request.

Sources