JAVASCRIPT
Cancel Pending Fetch API Requests
Learn how to effectively cancel ongoing Fetch API requests using AbortController, improving performance and preventing race conditions in your web apps.
let currentRequestController = null; // To keep track of the last active controller
async function fetchCancellableData(url) {
// If there's an ongoing request, cancel it
if (currentRequestController) {
currentRequestController.abort();
console.log('Previous request aborted.');
}
currentRequestController = new AbortController();
const signal = currentRequestController.signal;
try {
console.log(`Fetching data from: ${url}`);
const response = await fetch(url, { signal });
// Reset the controller after successful completion
currentRequestController = null;
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: response.statusText }));
throw new Error(`API Error: ${response.status} - ${errorData.message}`);
}
const data = await response.json();
console.log('Data fetched successfully:', data);
return data;
} catch (error) {
// Check if the error is due to abortion
if (error.name === 'AbortError') {
console.warn('Fetch request was aborted.');
} else {
console.error('Fetch error:', error);
}
// Reset the controller even on error (unless it was an abort initiated by this logic)
if (error.name !== 'AbortError' || !currentRequestController) {
currentRequestController = null;
}
throw error; // Re-throw to propagate the error
}
}
// Example Usage:
// const API_URL_1 = 'https://jsonplaceholder.typicode.com/posts/1';
// const API_URL_2 = 'https://jsonplaceholder.typicode.com/posts/2';
// const API_URL_SLOW = 'https://httpbin.org/delay/5'; // A slow endpoint for demonstration
// // Simulate rapid requests, where the first one should be cancelled
// fetchCancellableData(API_URL_SLOW).catch(() => {}); // This will likely be aborted
// setTimeout(() => fetchCancellableData(API_URL_1).then(data => console.log('Final data:', data)).catch(() => {}), 100);
// setTimeout(() => fetchCancellableData(API_URL_2).then(data => console.log('Final data:', data)).catch(() => {}), 200);
// // You can also manually abort if needed (e.g., user navigates away)
// // if (currentRequestController) {
// // currentRequestController.abort();
// // currentRequestController = null;
// // console.log('Manually aborted request.');
// // }
How it works: This snippet demonstrates how to cancel ongoing Fetch API requests using the `AbortController` interface. This is crucial for improving performance and preventing race conditions, especially in scenarios like search bars (where previous requests become stale) or component unmounts (to avoid updating unmounted components). An `AbortController` creates an `AbortSignal` that can be passed to a `fetch` request. When the `abort()` method is called on the controller, the associated `fetch` request is terminated, causing the promise to reject with an `AbortError`. The example includes logic to track and automatically cancel previous requests before initiating a new one, ensuring only the most recent request is processed.