Monday, April 25, 2016

Retry mechanism for JavaScript

I was recently asked to work on a retry mechanism in JavaScript so API calls to save data could be more robust. I built it as a asynchronous decorative combinator so it is nicely independent from the API call it is retrying. It is a nice piece of code so I will include it here. Note that I built it using the ES6 browser built in Promise library. It should be relatively straight forward to change this to use another Promise library. The jsfiddle where I developed and tested this is at https://jsfiddle.net/willseitz/x32e0Ldt/. Note that this fiddle may not work in all browsers because your browser may not be ES6 compliant.

function wait(duration) {
    return new Promise((resolve, reject) => {
        setTimeout(resolve, duration)
    })
}


The above is just a fairly generic wait Promise. I use it to inject a delay between retries.

var retryOnFailure = (functionToRetry, timesToRetry, delay) => {
  return function(...args) {
    var retryCount = timesToRetry;
    var failureReason;
    var functionToIterate = function(...args) {
      if (retryCount < 1) { 
        return Promise.reject(failureReason);
      } else {
        retryCount--;
        return functionToRetry(...args)
          .catch((err) => {
            failureReason = err;
            return wait(delay)
              .then(() => { return functionToIterate(...args)});
          })
      }
    }
    return functionToIterate(...args);
  }
}

The above function was built of the identity combinator for JavaScript that I mentioned here. It has some interesting difference in that it names the returned function so that it can be called recursively and the closure is generated on each call instead of being shared between calls. I have highlighted all the areas that are library dependent (almost all libraries handle 'then' and 'catch') in red. To use the function you do something like the following

mySubmitFunction = retryOnFailure(mySubmitFunction,5,300);

The assumption here is that 'mySubmitFunction' returns a Promise. Also I have not checked this for context preservation and may need to be modified to preserve 'this'. There is also ES6 syntax in here beytond just the Promise library. I also use the spread notation so this should be passed through a transpiler. The TypeScript Playground is a simple online one that will handle the language features used here.

No comments:

Post a Comment