wretch-middlewares
Version:
Middlewares for the wretch library
106 lines • 4.86 kB
JavaScript
/* Defaults */
var defaultDelayRamp = function (delay, nbOfAttempts) { return (delay * nbOfAttempts); };
var defaultUntil = function (response) { return response && response.ok; };
var defaultResolver = function (response) { return response.clone(); };
/**
* ## Retry middleware
*
* #### Retries a request multiple times in case of an error (or until a custom condition is true).
*
* **Options**
*
* - *delayTimer* `milliseconds`
*
* > The timer between each attempt.
*
* > *(default: 500)*
*
* - *delayRamp* `(delay, nbOfAttempts) => milliseconds`
*
* > The custom function that is used to calculate the actual delay based on the the timer & the number of attemps.
*
* > *(default: delay * nbOfAttemps)*
*
* - *maxAttempts* `number`
*
* > The maximum number of retries before resolving the promise with the last error. Specifying 0 means infinite retries.
*
* > *(default: 10)*
*
* - *until* `(response, error) => boolean || Promise<boolean>`
*
* > The request will be retried until that condition is satisfied.
*
* > *(default: response && response.ok)*
*
* - *onRetry* `({ response, error, url, options }) => { url?, options? } || Promise<{url?, options?}>`
*
* > Callback that will get executed before retrying the request. If this function returns an object having url and/or options properties, they will override existing values in the retried request.
*
* > *(default: null)*
*
* - *retryOnNetworkError* `boolean`
*
* > If true, will retry the request if a network error was thrown. Will also provide an 'error' argument to the `onRetry` and `until` methods.
*
* > *(default: false)*
*
* - *resolver* `(response: Response) => Response`
*
* > This function is called when resolving the fetch response from duplicate calls.
* By default it clones the response to allow reading the body from multiple sources.
*
* > *(default: response => response.clone())*
*/
export var retry = function (_a) {
var _b = _a === void 0 ? {} : _a, _c = _b.delayTimer, delayTimer = _c === void 0 ? 500 : _c, _d = _b.delayRamp, delayRamp = _d === void 0 ? defaultDelayRamp : _d, _e = _b.maxAttempts, maxAttempts = _e === void 0 ? 10 : _e, _f = _b.until, until = _f === void 0 ? defaultUntil : _f, _g = _b.onRetry, onRetry = _g === void 0 ? null : _g, _h = _b.retryOnNetworkError, retryOnNetworkError = _h === void 0 ? false : _h, _j = _b.resolver, resolver = _j === void 0 ? defaultResolver : _j;
return function (next) { return function (url, opts) {
var numberOfAttemptsMade = 0;
var checkStatus = function (response, error) {
return Promise.resolve(until(response && response.clone(), error)).then(function (done) {
// If the response is unexpected
if (!done) {
numberOfAttemptsMade++;
if (!maxAttempts || numberOfAttemptsMade <= maxAttempts) {
// We need to recurse until we have a correct response and chain the checks
return new Promise(function (resolve) {
var delay = delayRamp(delayTimer, numberOfAttemptsMade);
setTimeout(function () {
if (typeof onRetry === 'function') {
Promise.resolve(onRetry({
response: response && resolver(response),
error: error,
url: url,
options: opts
})).then(function (values) {
if (values === void 0) { values = {}; }
resolve(next(values.url || url, values.options || opts));
});
}
else {
resolve(next(url, opts));
}
}, delay);
}).then(checkStatus).catch(function (error) {
if (!retryOnNetworkError)
throw error;
return checkStatus(null, error);
});
}
else {
return Promise.reject(error || new Error('Number of attempts exceeded.'));
}
}
return error ? Promise.reject(error) : response;
});
};
return next(url, opts)
.then(checkStatus)
.catch(function (error) {
if (!retryOnNetworkError)
throw error;
return checkStatus(null, error);
});
}; };
};
//# sourceMappingURL=index.js.map