Instantly share code, notes, and snippets.

Embed
What would you like to do?
A few general patterns for retries using promises
function keepTrying(otherArgs, promise) {
promise = promise||new Promise();
// try doing the important thing
if(success) {
promise.resolve(result);
} else {
setTimeout(function() {
keepTrying(otherArgs, promise);
}, retryInterval);
}
}
function keepTrying(otherArgs, retryInterval, promise) {
promise = promise||new Promise();
// try doing the important thing
if(success) {
promise.resolve(result);
} else {
setTimeout(function() {
// Try again with incremental backoff, 2 can be
// anything you want. You could even pass it in.
// Cap max retry interval, which probably makes sense
// in most cases.
keepTrying(otherArgs, Math.min(maxRetryInterval, retryInterval * 2), promise);
}, retryInterval);
}
}
function tryAtMost(otherArgs, maxRetries, promise) {
promise = promise||new Promise();
// try doing the important thing
if(success) {
promise.resolve(result);
} else if (maxRetries > 0) {
// Try again if we haven't reached maxRetries yet
setTimeout(function() {
tryAtMost(otherArgs, maxRetries - 1, promise);
}, retryInterval);
} else {
promise.reject(error);
}
}
@spacenick

This comment has been minimized.

spacenick commented Aug 26, 2014

Hey thanks for sharing, if that can help I'm using this (requires Q though)

var retryPromise = function(promise, args, maxTries, context) {
    context = context || null;
    return promise.apply(context, args)
    .then(function(d){
        return Q(d);
    },
    function(err){
        if (maxTries == -1) return Q.error(err);
        else return retryPromise(promise, args, maxTries - 1);
    }):
}

And you'd use it like that :

var promise = retryPromise(dataStore.loadMovies, [my, Arguments], 3,  dataStore)
.then(...)
@MichaelJCole

This comment has been minimized.

MichaelJCole commented Dec 12, 2014

Hey, what Promise library are you using? This doesn't appear to be EMCA 6 compatible: promise = promise||new Promise();

If you're looking for a Q solution, check this out: https://gist.github.com/kriskowal/593052

@jansoren

This comment has been minimized.

jansoren commented Sep 27, 2016

👍

@yandzee

This comment has been minimized.

@samjross

This comment has been minimized.

samjross commented May 9, 2018

@spacenick function(err){ if (maxTries == -1) return Q.error(err); swallows the error

@curran

This comment has been minimized.

curran commented Jul 6, 2018

An alternative solution:

const retry = (fn, ms) => new Promise(resolve => { 
  fn()
    .then(resolve)
    .catch(() => {
      setTimeout(() => {
        console.log('retrying...');
        retry(fn, ms).then(resolve);
      }, ms);
    })
});

Related: GoogleChrome/puppeteer#2460

@r3wt

This comment has been minimized.

r3wt commented Aug 9, 2018

@curran 's solution with max retries

const retry = (fn, ms=1000,maxRetries=5) => new Promise((resolve,reject) => { 
    var retries=0;
    fn()
    .then(resolve)
    .catch(() => {
        setTimeout(() => {
            console.log('retrying failed promise...');
            ++retries;
            if(retries==maxRetries) {
                return reject('maximum retries exceeded');
            }
            retry(fn, ms).then(resolve);
        }, ms);
    })
});
@Alfafc

This comment has been minimized.

Alfafc commented Sep 7, 2018

@r3wt thanks!

@eliseumds

This comment has been minimized.

eliseumds commented Sep 11, 2018

Thanks @r3wt!

I'd modify the code a bit because I wasn't being able to catch the max retries exception. Also, we don't really need a counter:

function retry(fn, retriesLeft = 5, interval = 1000) {
  return new Promise((resolve, reject) => {
    fn()
      .then(resolve)
      .catch((error) => {
        setTimeout(() => {
          if (retriesLeft === 1) {
            // reject('maximum retries exceeded');
            reject(error);
            return;
          }

          // Passing on "reject" is the important part
          retry(fn, interval, retriesLeft - 1).then(resolve, reject);
        }, interval);
      });
  });
}
@dinigo

This comment has been minimized.

dinigo commented Nov 8, 2018

Heres an ES6, async/await version. Thank you guys! https://gitlab.com/snippets/1775781

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment