2

I am trying to figure out how to create a generic retry function that exponentially backs off for any promise passed to it. It looks like everything is working except for a couple things. If the function resolves on the first try, then I see my resolve value and it logs out hey which is expected. If it resolves on any subsequent call, it does not log out hey. If it rejects, I get a couple deprecation warnings which I haven't looked into yet. Here is the code...

function retry(func, max, time) {
    console.log(max);
    return new Promise((resolve, reject) => {
        func()
            .then(r => resolve(r))
            .catch(err => {
                if (max === 0) {
                    reject(err);
                } else {
                    setTimeout(function(){
                        retry(func, --max, time * 2);
                    }, time);
                }
            });
    });
}

const promise = retry(function () {
    return new Promise((resolve, reject) => {
        const rand = Math.random();
        if (rand >= 0.8) {
            resolve('hey');
        } else {
            reject(new Error('oh noes'));
        }
    });
}, 5, 100);

promise.then(r => console.log(r)).catch(err => console.log(err));

Any help would be appreciated.

Mr. Ant
  • 700
  • 2
  • 15
  • 32
  • 3
    You never actually resolve the original promise when you retry. – SLaks May 09 '18 at 21:20
  • @SLaks I don't want to resolve anything until the actual func being executed resolves. Can you tell me exactly what needs to change in the code? – Mr. Ant May 09 '18 at 21:29
  • When you call `retry()`, you need to resolve the original promise once it finishes (by calling `resolve()`) – SLaks May 09 '18 at 21:30
  • @SLaks I tried to call resolve() in a few different places and still am not getting it. :( Can you be more specific? – Mr. Ant May 09 '18 at 21:35

1 Answers1

1

Here is a working example

/**
 * Function to retry
 */
function retry(func, max, time) {
  return new Promise((resolve, reject) => {
    apiFunction()
      .then(resolve)
      .catch(err => {
        if (max === 0) {
          return reject(err);
        } else {
          setTimeout(function() {
            retry(func, --max, time * 2)
              .then(resolve)
              .catch(reject);
          }, time);
        }
      });
  });
}

/**
 * Function to test out
 */
const apiFunction = () => new Promise((resolve, reject) => {
  const rand = Math.random();

  if (rand >= 0.8) {
    console.log('Works');
    
    resolve('hey');
  } else {
    console.log('fail');
    
    reject(new Error('oh noes'));
  }
});

retry(apiFunction, 5, 10)
  .then(() => console.log('all done ok'))
  .catch(() => console.log('all done error'));
Orelsanpls
  • 22,456
  • 6
  • 42
  • 69