close
close

api – How to create a promise-based retry function in vanilla JavaScript?

api – How to create a promise-based retry function in vanilla JavaScript?

I am working on a web application where I need to make API requests. It needs to be robust and assume that it may fail due to network or server errors. I want to have a retry function that keeps making a certain number of calls before stopping.

I need to improve this function so that it can handle 2 cases. 1) Cancellation. Suppose the user closes the browser or navigates to another part of the page. The current function has no way to cancel the current attempts. 2) Handle some error codes. Suppose you get a 4xx HTTP error code. There is no point in retrying because it could be unauthorized (401) or forbidden (403). But, it should retry for 5xx error codes. My current function does not provide a way to differentiate between different error codes.

Here is the minimal reproducible example I have for you:

function retry(fn, retries = 3, delay = 1000) {
    return new Promise((resolve, reject) => {
        let attempt = (n) => {
            fn().then(resolve)
              .catch((error) => {
                if (n === 0) {
                    reject(error)
                } else {
                    setTimeout(() => {
                        
                    }, delay); // 1 second delay default
                }
              });
        };
        attempt(retries);
    })
}

// Test
let fetchWithRetry = () => retry(() => fetch("https://jsonplaceholder.typicode.com/todos/95"));

fetchWithRetry()
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(error => console.error('Failed to fetch data:', error));

I found another Stack Overflow answer regarding retry logic, but it doesn’t fully address the need for cancellation and specific HTTP error codes. Promise Retry Design Patterns