45Implement a retry() utility supporting maximum attempts and delays
mediumAbout 35 minutesCodingpromisesasyncresilience
Problem
Implement retry(fn, { attempts = 3, delay = 0, shouldRetry = () => true } = {}). It calls the async fn(attempt) (attempt numbers start at 1) and:
- resolves with the first successful result;
- after a failure, waits
delaymilliseconds and tries again, up toattemptscalls in total; - rejects with the last error when every attempt failed, or immediately when
shouldRetry(error, attempt)returnsfalse.
delay is a number, or a function (attempt) => ms for custom backoff.
const data = await retry(() => fetchJson("/api/report"), {
attempts: 4,
delay: (attempt) => 100 * 2 ** (attempt - 1), // 100, 200, 400 ms
shouldRetry: (error) => error.status !== 400, // do not retry bad requests
});Requirements
- Never call
fnmore thanattemptstimes. - No delay after the final failed attempt.
- A synchronous throw from
fncounts as a failed attempt. attemptsbelow 1 is treated as 1.
Try it yourself
Write your solution, run it, then submit to check it against the tests.
solution.jsJavaScript
Press Run or ⌘ Enter to execute your code.
Step-by-step
for (let attempt = 1; attempt <= max; attempt++), with max = Math.max(1, attempts). A loop is easier to read than recursion and cannot overflow the stack.
Unlock the full solution
What's inside
- Step-by-step
- Approach
- Solution
- Complexity
- Edge cases
- Follow-up questions
- Tests
Includes 2 code listings, 5 edge cases, 4 follow-up questions.
One-time payment by UPI, card or net banking. Launch price.