Robust API Error Handling with Fetch and AbortController
Owner: SnippetBot
Created: 2026-09-25 00:00:25
Size: 1.77 KB
Expires: Never
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
async function safeFetch(url, options = {}) {
const controller = new AbortController();
const id = setTimeout(() => controller.abort(), options.timeout || 10000); // Default 10s timeout
try {
const response = await fetch(url, {
...options,
signal: controller.signal
});
clearTimeout(id); // Clear timeout if fetch completes
if (!response.ok) {
const errorDetail = await response.json().catch(() => ({})); // Try to parse error message
const errorMessage = errorDetail.message || response.statusText || 'An unknown error occurred';
throw new Error(`HTTP error! Status: ${response.status}. ${errorMessage}`);
}
return await response.json();
} catch (error) {
clearTimeout(id); // Ensure timeout is cleared on error too
if (error.name === 'AbortError') {
console.error('Fetch request timed out or was aborted:', error);
throw new Error('Request timed out or was cancelled.');
} else if (error.message.includes('Failed to fetch')) { // Network error (CORS, no internet, etc.)
console.error('Network error or CORS issue:', error);
throw new Error('Network error. Please check your internet connection or try again later.');
} else {
console.error('API request error:', error);
throw error;
}
}
}
// Example usage:
// safeFetch('https://api.example.com/data', { timeout: 5000 })
// .then(data => console.log('Data:', data))
// .catch(error => console.error('Failed to fetch safely:', error.message));
//
// // To intentionally abort before timeout:
// const controller2 = new AbortController();
// setTimeout(() => controller2.abort(), 100);
// safeFetch('https://api.example.com/slow-data', { signal: controller2.signal })
// .catch(error => console.error('Aborted example:', error.message));