Skip to content

Instantly share code, notes, and snippets.

@ntd251
Last active April 19, 2017 02:06
Show Gist options
  • Save ntd251/8079a5a6bd6e5aad6783c812bb62ae0c to your computer and use it in GitHub Desktop.
Save ntd251/8079a5a6bd6e5aad6783c812bb62ae0c to your computer and use it in GitHub Desktop.
Retry a promise until succeed or reach max retry count
/**
* Retry a promise until succeed or reach max retry count.
*
* Options includes:
* - maxRetryCount:
* If -1 -> retry until success. Terminate if exceed max count.
* If 0 -> No retry
* Default: -1
*
* - retryPeriod: Timer period. Default: 3 seconds;
*
* @author ntd251
* @param {function} requestFn - Function that returns the targeted promise
* @param {hash} options - Configuration
* @return {promise}
* @example
* ```js
* let requestFn = () => {
* return new Promise((resolve, reject) => {
* $.ajax({
* ...,
* success: resolve,
* error: reject,
* });
* });
* };
*
* // Retry until success
* //
* retryPromise(requestFn);
*
* // Retry maximum 3 times, with 1 second interval
* //
* retryPromise(requestFn, {
* retryPeriod: 1000,
* maxRetryCount: 3,
* });
*
* // Do not retry... errhhh I'm not sure if this would ever be used.
* // similar to `requestFn()`
* //
* retryPromise(requestFn, {
* maxRetryCount: 0,
* });
* ```
*/
function retryPromise(requestFn, options) {
options = options || {};
/**
* By default, retry until success
*/
let maxRetryCount = options.maxRetryCount;
if (typeof options.maxRetryCount === 'undefined') {
maxRetryCount = -1;
}
let retryPeriod = options.retryPeriod || 3000;
let retryCount = 0;
let loading = false;
let error;
let timer;
let terminateTimer = () => {
window.clearInterval(timer);
};
return new Promise((resolve, reject) => {
let sendRequest = () => {
loading = true;
requestFn().then((response) => {
/**
* Resolve and terminate
*/
resolve(response);
terminateTimer();
}, (error) => {
if (maxRetryCount >= 0 && retryCount >= maxRetryCount) {
/**
* Reject and terminate
* If maxRetryCount = 0. Immediately reject and terminate.
*/
reject(error);
terminateTimer();
} else {
/**
* Continue
*/
retryCount++;
}
}).finally(() => {
loading = false;
});
};
timer = window.setInterval(() => {
if (!loading) {
sendRequest();
}
}, retryPeriod);
sendRequest();
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment