JAVASCRIPT
Robust API Fetch with Cancellation and Timeout
Learn to make robust API requests in JavaScript using `fetch`, `AbortController` for cancellation, and a custom timeout mechanism for better error handling and resource management.
async function robustFetch(url, options = {}, timeout = 10000) {
const controller = new AbortController();
const id = setTimeout(() => controller.abort(), timeout);
try {
const response = await fetch(url, {
...options,
signal: controller.signal
});
clearTimeout(id); // Clear timeout if fetch completes in time
if (!response.ok) {
let errorData;
const contentType = response.headers.get('content-type');
if (contentType && contentType.includes('application/json')) {
errorData = await response.json();
} else {
errorData = await response.text();
}
throw new Error(`HTTP error! Status: ${response.status}
Details: ${JSON.stringify(errorData)}`);
}
return await response.json(); // Assuming JSON response
} catch (error) {
if (error.name === 'AbortError') {
throw new Error('Request timed out or was cancelled.');
}
// Re-throw other errors for further handling
throw error;
}
}
// Example Usage:
// (async () => {
// try {
// const data = await robustFetch('https://jsonplaceholder.typicode.com/posts/1', {}, 5000);
// console.log('Fetched data:', data);
// } catch (error) {
// console.error('Fetch error:', error.message);
// }
// // Example of a request that might time out (adjust URL/timeout if needed)
// // try {
// // const slowData = await robustFetch('https://httpbin.org/delay/10', {}, 2000); // This will time out
// // console.log('Fetched slow data:', slowData);
// // } catch (error) {
// // console.error('Slow fetch error:', error.message);
// // }
// })();
How it works: This JavaScript snippet provides a robust `fetch` wrapper. It incorporates `AbortController` to allow for request cancellation, which is essential for implementing a custom timeout mechanism. If the `fetch` request doesn't complete within the specified `timeout` duration, the `AbortController` will cancel the request, preventing hanging promises. It also includes comprehensive error handling, checking `response.ok` and parsing error details from the response body (JSON or text) before throwing a more informative error. This pattern enhances reliability and user experience by preventing indefinite loading states and providing clear failure reasons.