JAVASCRIPT
Resilient API Requests with Exponential Backoff
Implement a robust retry mechanism with exponential backoff for API requests in JavaScript, improving fault tolerance against temporary network or server issues. Essential for resilient API integrations.
async function fetchWithExponentialBackoff(url, options = {}, retries = 3, delay = 1000) {
for (let i = 0; i < retries; i++) {
try {
const response = await fetch(url, options);
if (!response.ok) {
// Treat non-OK responses (e.g., 5xx, 429 Too Many Requests) as retriable errors
// You might want to fine-tune which statuses are retriable
throw new Error(`HTTP error! status: ${response.status}`);
}
return response; // Success!
} catch (error) {
console.warn(`Request failed (attempt ${i + 1}/${retries}): ${error.message}`);
if (i < retries - 1) {
const backoffDelay = delay * Math.pow(2, i) + Math.random() * 1000; // Exponential + jitter
console.log(`Retrying in ${backoffDelay}ms...`);
await new Promise(resolve => setTimeout(resolve, backoffDelay));
} else {
throw error; // Last attempt failed, re-throw the error
}
}
}
}
// Example Usage:
(async () => {
try {
const data = await fetchWithExponentialBackoff('https://jsonplaceholder.typicode.com/posts/1', {
method: 'GET'
}, 5); // Try up to 5 times
const json = await data.json();
console.log('Successfully fetched data:', json);
} catch (error) {
console.error('Failed to fetch data after multiple retries:', error);
}
// Example of a potentially failing request (e.g., intentionally bad URL or rate-limited mock)
// Note: jsonplaceholder might not return 5xx errors for non-existent routes,
// so this example assumes a service that might transiently fail.
try {
const failingData = await fetchWithExponentialBackoff('https://httpstat.us/503', {}, 3, 500); // Simulate 503 error
const text = await failingData.text(); // 503 response body
console.log('Successfully fetched failing data (should not happen if 503 is always returned):', text);
} catch (error) {
console.error('Expected failure for 503 simulation:', error);
}
})();
How it works: This JavaScript snippet provides a resilient `fetch` wrapper that retries failed API requests using an exponential backoff strategy with added jitter. If an HTTP request fails due to network issues or a server error (e.g., 5xx status codes, or 429 Too Many Requests), the function waits for an exponentially increasing delay before attempting the request again. Jitter is added to prevent all clients from retrying simultaneously, reducing server load during recovery. This enhances the robustness of API integrations against transient failures.