FrontendPro

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 delay milliseconds and tries again, up to attempts calls in total;
  • rejects with the last error when every attempt failed, or immediately when shouldRetry(error, attempt) returns false.

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 fn more than attempts times.
  • No delay after the final failed attempt.
  • A synchronous throw from fn counts as a failed attempt.
  • attempts below 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.

All 150 answersOne payment, yours forever