Quiz

How do you abort a web request using `AbortController` in JavaScript?

Topics
JavaScriptNetworking
Edit on GitHub

TL;DR

AbortController is used to cancel ongoing asynchronous operations like fetch requests.

const controller = new AbortController();
const signal = controller.signal;
fetch('https://jsonplaceholder.typicode.com/todos/1', { signal })
.then((response) => {
// Handle response
})
.catch((error) => {
if (error.name === 'AbortError') {
console.log('Request aborted');
} else {
console.error('Error:', error);
}
});
// Call abort() to abort the request
controller.abort();

Aborting web requests is useful for:

  • Canceling requests based on user actions.
  • Prioritizing the latest requests in scenarios with multiple simultaneous requests.
  • Canceling requests that are no longer needed, e.g. after the user has navigated away from the page.

AbortControllers

AbortController allows graceful cancelation of ongoing asynchronous operations like fetch requests. It offers a mechanism to signal to the underlying network layer that the request is no longer required, preventing unnecessary resource consumption and improving user experience.

Using AbortControllers

Using AbortControllers involve the following steps:

  1. Create an AbortController instance: Initialize an AbortController instance, which creates a signal that can be used to abort requests.
  2. Pass the signal to the request: Pass the signal to the request, typically through the signal property in the request options.
  3. Abort the request: Call the abort() method on the AbortController instance to cancel the ongoing request.

Here is an example of how to use AbortControllers with the fetch() API:

const controller = new AbortController();
const signal = controller.signal;
fetch('https://jsonplaceholder.typicode.com/todos/1', { signal })
.then((response) => {
// Handle response
})
.catch((error) => {
if (error.name === 'AbortError') {
console.log('Request aborted');
} else {
console.error('Error:', error);
}
});
// Call abort() to abort the request
controller.abort();

Use cases

Canceling a fetch() request on a user action

Cancel requests that take too long or are no longer relevant due to user interactions (e.g., user cancels uploading of a huge file).

// HTML:
// <div>
// <button id="cancel-button">Cancel upload</button>
// </div>
const controller = new AbortController();
const signal = controller.signal;
fetch('https://jsonplaceholder.typicode.com/todos/1', { signal })
.then((response) => {
// Handle successful response
})
.catch((error) => {
if (error.name === 'AbortError') {
console.log('Request canceled');
} else {
console.error('Network or other error:', error);
}
});
document.getElementById('cancel-button').addEventListener('click', () => {
controller.abort();
});

When you click the "Cancel upload" button, in-flight request will be aborted.

Prioritizing latest requests in a race condition

In scenarios where multiple requests are initiated for the same data, use AbortController to prioritize the latest request and abort earlier ones.

let latestController = null; // Keeps track of the latest controller
function fetchData(url) {
if (latestController) {
latestController.abort(); // Abort any previous request
}
const controller = new AbortController();
latestController = controller;
const signal = controller.signal;
fetch(url, { signal })
.then((response) => {
// Handle successful response
})
.catch((error) => {
if (error.name === 'AbortError') {
console.log('Request canceled');
} else {
console.error('Network or other error:', error);
}
});
}

In this example, when the fetchData() function is called multiple times triggering multiple fetch requests, AbortControllers will cancel all the previous requests except the latest request. This is common in scenarios like type-ahead search or infinite scrolling, where new requests are triggered frequently.

Canceling requests that are no longer needed

In situations where the user has navigated away from the page, aborting the request can prevent unnecessary operations (e.g. success callback handling), and freeing up resources by lowering the likelihood of memory leaks.

Notes

  • AbortControllers is not fetch()-specific, it can be used to abort other asynchronous tasks as well.
  • A singular AbortContoller instance can be reused or multiple async tasks and cancel all of them at once.
  • Calling abort() on AbortControllers does not send any notification or signal to the server. The server is unaware of the cancelation and will continue processing the request until it completes or times out.

Further reading

Edit on GitHub