JAVASCRIPT
Cancelling Fetch Requests with AbortController
Improve user experience and prevent race conditions by learning to cancel pending `fetch` API requests using `AbortController` in JavaScript, especially useful for search or navigation.
let currentController = null; // To keep track of the last controller for cancellation
async function fetchDataWithCancellation(url, options = {}) {
if (currentController) {
currentController.abort(); // Abort previous pending request
console.log('Previous request aborted.');
}
currentController = new AbortController();
const signal = currentController.signal;
try {
const response = await fetch(url, { ...options, signal });
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
currentController = null; // Clear controller once request is complete
return data;
} catch (error) {
if (error.name === 'AbortError') {
console.log('Fetch request was aborted.');
} else {
console.error('Fetch error:', error);
throw error;
}
currentController = null; // Clear controller on error or abort
}
}
// Example Usage:
// // Simulating rapid calls, e.g., a type-ahead search
// const searchInput = document.getElementById('search-box');
// searchInput.addEventListener('input', debounce(async (event) => {
// const query = event.target.value;
// if (query.length > 2) {
// try {
// const data = await fetchDataWithCancellation(`https://api.example.com/search?q=${query}`);
// console.log('Search results:', data);
// // Render results
// } catch (error) {
// // Handle aborted or other errors
// }
// }
// }, 300)); // Using a debounce function to limit API calls
// // Debounce helper function (not part of the core snippet but often used with AbortController)
// function debounce(func, delay) {
// let timeout;
// return function(...args) {
// const context = this;
// clearTimeout(timeout);
// timeout = setTimeout(() => func.apply(context, args), delay);
// };
// }
How it works: This snippet demonstrates how to use `AbortController` to cancel pending `fetch` requests. Before making a new request, it checks if a previous one is still active and aborts it. This is crucial for scenarios like type-ahead search or tab switching where multiple requests might be fired rapidly, preventing stale responses and reducing unnecessary network traffic, thereby improving user experience.