Skip to content

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.

Copy link

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.

Copy link

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.

Copy link

commented Sep 27, 2016

👍

@yandzee

This comment has been minimized.

@samjross

This comment has been minimized.

Copy link

commented May 9, 2018

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

@curran

This comment has been minimized.

Copy link

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.

Copy link

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.

Copy link

commented Sep 7, 2018

@r3wt thanks!

@eliseumds

This comment has been minimized.

Copy link

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.

Copy link

commented Nov 8, 2018

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

@catchergeese

This comment has been minimized.

Copy link

commented Feb 13, 2019

@eliseumds If case you ever needed to debug it, you (I reckon accidentally) flipped arguments to retry there retry(fn, interval, retriesLeft - 1).then(resolve, reject);, it should be retry(fn, retriesLeft - 1, interval).then(resolve, reject);

@pettomartino

This comment has been minimized.

Copy link

commented Mar 12, 2019

@eliseumds

if (retriesLeft === 1) {
// reject('maximum retries exceeded');
  return reject(error);
}

I think that should be outside setTimeout

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.