Skip to content

Latest commit

 

History

History
81 lines (60 loc) · 2.57 KB

64.auto-retry-Promise-on-rejection.md

File metadata and controls

81 lines (60 loc) · 2.57 KB

64. auto-retry Promise on rejection

Problem

https://bigfrontend.dev/problem/retry-promise-on-rejection

Problem Description

For a web application, fetching API data is a common task.

But the API calls might fail because of Network problems. Usually we could show a screen for Network Error and ask users to retry.

One approach to handle this is auto retry when network error occurs.

You are asked to create a fetchWithAutoRetry(fetcher, count), which automatically fetch again when error happens, until the maximum count is met.

For the problem here, there is no need to detect network error, you can just retry on all promise rejections.

Understanding the problem

Write a function that retries fetch upon failure up to N times. The function takes two inputs, a callback function that fetches API data and returns a promise, and an integer representing maximum retry count.

Approach

Fetching data is always asynchronous, so the function needs to return a promise. Within the promise, we can use a try...catch block to implement the auto retry. Call the fetcher function in the try block and then resolve the result. If an error is thrown in the try block, the statement in the catch block will be executed. So in the catch block, we can try to fetch the data again if the maximum count is not reached. We can use the variable maximumRetryCount to keep track of how many tries we have left. Every time we retry, we decrease the maximumRetryCount by 1. If maximumRetryCount is equal to 0, the returned promise gets rejected with the thrown error as its value.

Solution

/**
 * @param {() => Promise<any>} fetcher
 * @param {number} maximumRetryCount
 * @return {Promise<any>}
 */
function fetchWithAutoRetry(fetcher, maximumRetryCount) {
  return new Promise((resolve, reject) => {
    const retry = async (retriesLeft) => {
      try {
        const data = await fetcher();
        resolve(data);
      } catch (err) {
        if (retriesLeft === 0) {
          reject(err);
          return;
        }
        retry(retriesLeft - 1);
      }
    };
    retry(maximumRetryCount);
  });
}

Usage

const fetcher = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      fetch("https://jsonplaceholder.typicode.com/posts")
        .then((response) => response.json())
        .then((data) => resolve(data))
        .catch((err) => reject(err));
    }, 1000);
  });
};

console.log("Start");
fetchWithAutoRetry(fetcher, 5)
  .then((data) => console.log(data))
  .catch((err) => console.log(err));
console.log("End");