Implement a Retry Function for a Promise in JavaScript

In many real-world scenarios, especially when making network requests, temporary failures are common. A common interview question is to implement a Retry function for promise up to N times before rejecting it.

In this article, we’ll break down how to implement this function step by step.

πŸ§‘β€πŸ’» Problem Statement

Implement a retryPromise function that accepts a promise-returning function and retries it up to n times if it fails. If all attempts fail, it should reject with the last error.

const unreliableNetworkCall = () => {
  return new Promise((resolve, reject) => {
    if (Math.random() > 0.7) resolve("Success!");
    else reject("Failed!");
  });
};

retryPromise(unreliableNetworkCall, 3)
  .then(result => console.log(result))
  .catch(error => console.error(error));

In this example, retryPromise will try calling unreliableNetworkCall up to 3 times before rejecting the promise.

πŸ’‘ Plan & Approach for Retry Function

We’ll implement the retryPromise function with the following steps:

  1. Accept a promise-returning function and retry count.
  2. Use a recursive or loop-based approach to retry the promise.
  3. Resolve if successful; reject after N failures.

πŸ› οΈ Solution: Recursive Approach

Here’s a recursive implementation of retryPromise.

function retryPromise(fn, retries) {
  return new Promise((resolve, reject) => {
    function attempt(remainingRetries) {
      fn()
        .then(resolve)
        .catch((error) => {
          if (remainingRetries === 0) {
            reject(error);
          } else {
            console.log(`Retrying... Attempts left: ${remainingRetries}`);
            attempt(remainingRetries - 1);
          }
        });
    }

    attempt(retries);
  });
}

πŸ” Explanation:

  1. retryPromise(fn, retries): Takes a promise-returning function fn and the number of retries.
  2. Recursive function attempt(remainingRetries):
    • Calls the function fn.
    • If it succeeds (.then), resolve the promise.
    • If it fails (.catch), retry until remainingRetries reaches 0.
  3. Logs each retry and rejects with the last error if all retries fail.

πŸ› οΈ Solution: Iterative Approach

A loop-based solution can be more intuitive for some developers.

async function retryPromise(fn, retries) {
  let lastError;
  for (let i = 0; i <= retries; i++) {
    try {
      return await fn();
    } catch (error) {
      lastError = error;
      console.log(`Retry ${i + 1} failed.`);
    }
  }
  throw lastError;
}

πŸ” Explanation:

  1. for loop retries the promise up to retries times.
  2. If fn succeeds, it returns the result.
  3. If all attempts fail, it throws the last encountered error.

βœ… Use Cases & Best Practices

  • Network Requests: Retry failed HTTP requests due to temporary issues (e.g., server overload, network glitch).
  • Exponential Backoff: Add delay between retries to avoid overloading the system.
  • Configurable Retry Logic: Customize the number of retries, delays, and error-handling behaviour.

This question was asked in Zepto interview for the SDE2 Frontend role, and the question was shared on the LinkedIn Platform.