Implementing Chained retries with increasing Delays in JavaScript
Chained Retry with Delays:
Write a JavaScript program to implement a function that retries a failed asynchronous operation with increasing delays between attempts.
Solution-1: Using async/await and setTimeout
Code:
async function retryWithDelay(asyncFunction, retries, delay) {
for (let attempt = 1; attempt <= retries; attempt++) {
try {
// Try executing the asynchronous function
return await asyncFunction();
} catch (error) {
console.error(`Attempt ${attempt} failed:`, error.message);
if (attempt === retries) {
throw new Error('All retries failed'); // Throw error after all retries fail
}
// Wait for the specified delay before retrying
await new Promise((resolve) => setTimeout(resolve, delay * attempt));
}
}
}
// Example usage of retryWithDelay
const simulateAsyncTask = async () => {
if (Math.random() > 0.7) {
return 'Success!';
} else {
throw new Error('Random failure');
}
};
retryWithDelay(simulateAsyncTask, 5, 1000)
.then((result) => console.log('Operation succeeded:', result))
.catch((error) => console.error('Operation failed:', error.message));
Output:
"Attempt 1 failed:" "Operation succeeded:" Undefined
Explanation:
- 'asyncFunction' is executed inside a `try` block to handle potential errors.
- On failure, a delay is introduced using `setTimeout` before retrying.
- The delay increases with each retry (linear backoff).
Solution-2: Exponential Backoff
Code:
// Simulated asynchronous task that randomly succeeds or fails
async function simulateAsyncTask() {
// Randomly decide success or failure
if (Math.random() > 0.7) {
return "Success!";
} else {
throw new Error("Random failure");
}
}
// Function to retry an async operation with exponential backoff
async function retryWithExponentialBackoff(asyncFunction, retries, initialDelay) {
let delay = initialDelay; // Start with the initial delay
for (let attempt = 1; attempt <= retries; attempt++) {
try {
// Try executing the asynchronous function
return await asyncFunction();
} catch (error) {
console.error(`Attempt ${attempt} failed:`, error.message);
if (attempt === retries) {
throw new Error("All retries failed"); // Throw error after all retries fail
}
// Wait for the current delay before retrying
await new Promise((resolve) => setTimeout(resolve, delay));
delay *= 2; // Double the delay for exponential backoff
}
}
}
// Example usage of retryWithExponentialBackoff
retryWithExponentialBackoff(simulateAsyncTask, 5, 500)
.then((result) => console.log("Operation succeeded:", result))
.catch((error) => console.error("Operation failed:", error.message));
Output:
"Attempt 1 failed:" "Operation succeeded:" undefined
Explanation:
- Starts with an initial delay and doubles it after each failure (exponential backoff).
- Delays grow progressively to reduce the load on resources during retries.
- Retries stop once the maximum number of attempts is reached or the operation succeeds.
Key Differences:
- Solution 1 uses a linear backoff, increasing delay by a fixed amount.
- Solution 2 employs exponential backoff, doubling the delay each time.
See the Pen promises-and-async-await-exercise-20 by w3resource (@w3resource) on CodePen.
Improve this sample solution and post your code through Disqus
Previous: Optimize API Fetching: Parallel vs Sequential Methods Explained.
What is the difficulty level of this exercise?
Test your Programming skills with w3resource's quiz.
- Weekly Trends and Language Statistics
- Weekly Trends and Language Statistics