JAVASCRIPT
Cancel Pending API Requests with AbortController
Efficiently manage network requests by canceling in-flight fetch operations using `AbortController`, preventing stale data and improving application responsiveness.
let currentSearchController = null;
async function searchData(query) {
// If there's an existing request, abort it
if (currentSearchController) {
currentSearchController.abort();
console.log('Previous request aborted.');
}
currentSearchController = new AbortController();
const { signal } = currentSearchController;
try {
console.log(`Fetching data for query: "${query}"`);
const response = await fetch(`https://api.example.com/search?q=${encodeURIComponent(query)}`, { signal });
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const data = await response.json();
console.log('Search results:', data);
return data;
} catch (error) {
if (error.name === 'AbortError') {
console.log('Fetch aborted successfully.');
return null; // Return null or handle as cancelled
}
console.error('Fetch error:', error);
throw error;
} finally {
currentSearchController = null; // Clear controller once request is finished or aborted
}
}
// Usage example (e.g., in a search input handler):
// const searchInput = document.getElementById('searchInput');
// searchInput.addEventListener('input', debounce((event) => {
// const query = event.target.value;
// if (query.length > 2) { // Only search for queries longer than 2 chars
// searchData(query);
// } else if (currentSearchController) {
// currentSearchController.abort(); // Cancel if query becomes too short
// currentSearchController = null;
// }
// }, 300));
// A simple debounce function (not the main focus of this snippet, but useful for usage)
// 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 the `AbortController` API to cancel pending `fetch` requests. This is particularly useful in scenarios like search-as-you-type inputs, where rapid user input can trigger multiple requests, making previous ones obsolete. Before initiating a new request, any ongoing request is aborted using `currentSearchController.abort()`, preventing race conditions, saving bandwidth, and ensuring that only the results from the latest query are processed, thus improving performance and user experience.