1

I am using fetch API and try to implement a function which gets retry parameter and re-sends another request if the previous one was failed. I've found this answer and here is my code, Does anybody know how to write the function in none-recursion?

const fetchRetry = (url, delay, limit, fetchOptions = {}) => {
    return new Promise((resolve, reject) => {
        const success = (response) => resolve(response);

        const failure = (error) => {
            if (limit) {
                setTimeout(fetchUrl, delay)
            }
            else {
                // this time it failed for real
                reject(error);
            }
            limit--;
        }

        const finalHandler = (finalError) => { throw finalError };

        const fetchUrl = () => {
            return fetch(url, fetchOptions)
                .then(success)
                .catch(failure)
                .catch(finalHandler);
        }

        fetchUrl();
    });
}

fetchRetry('https://jsonplaceholder.typicode.commmmmm/posts/1', 1000, 3)
    .then((response) => {
        if (!response.ok) {
            throw new Error('failed!');
        }
        return response;
    })
    .then((response) => console.log(response))
    .catch((error) => console.log(error));
Andy
  • 23
  • 1
  • 5

1 Answers1

1

That could be made so much simpler:

var fetchRetry = (url, delay, limit, fetchOptions = {}) => {
  const later = delay =>
    new Promise(resolve=>setTimeout(resolve,delay));
  const recur = (timesTried,err) =>
    (timesTried>=limit)
      ? Promise.reject(err)
      : fetch(url, fetchOptions)
        .catch(
          err=>
            later(delay).then(
              ()=>recur(timesTried+1,err)
            )
        );
  return recur(0);
}

To not use a recurring function would probably make it more complicated. Maybe if you use async/await you can use a while loop and try/catch

However; anything recursive can usually be done with reduce and vice versa but it's best to not use reduce for very large number of retries:

var fetch=()=>console.log("trying") || Promise.reject("no");

const fetchRetry = (url, delay, limit, fetchOptions = {}) => {
  const later = delay =>
    new Promise(resolve=>setTimeout(resolve,delay));
  const tries = Array.from(new Array(limit),(item,index)=>index+1);
  return tries.reduce(
    (promise,value)=>
      promise.catch(
        err=>
          (value===tries.length)
            ? Promise.reject(err)
            : later(delay).then(()=>fetch(url,fetchOptions))
      ),
    fetch(url,fetchOptions)
  );
}
console.log("starting...");
fetchRetry("",1000,2)
.catch(err=>console.warn("error:",err));
HMR
  • 37,593
  • 24
  • 91
  • 160