Skip to content

Instantly share code, notes, and snippets.

@jesusgoku
Created August 1, 2020 00:00
Show Gist options
  • Save jesusgoku/03b82af517fcc7d1c138e5ad34d7fac4 to your computer and use it in GitHub Desktop.
Save jesusgoku/03b82af517fcc7d1c138e5ad34d7fac4 to your computer and use it in GitHub Desktop.
Wrapper for axios with timeout and retry
class Request {
constructor(baseURL, { timeout, ...options } = {}) {
this.timeout = timeout;
this.client = axios.create({
baseURL,
...options,
});
return new Proxy(this, {
get(target, property) {
if (["get", "post", "put", "patch", "delete"].includes(property)) {
return (url, options) =>
target.request(url, { ...options, method: property });
}
return Reflect.get(...arguments);
},
});
}
/**
* Make request
*
* @param {string} url - some options
* @param {Object} options - request options
* @param {number} options.retry - number of retries before rejected
* @param {number} options.retryDelay - ms delay for retry
* @param {number} options.retryDelayFactor - factor to increase delay in each retry
*
* @returns {Promise<axios.Response>}
*/
request(
url,
{
timeout,
retry = 0,
retryDelay = 100,
retryDelayFactor = 2,
...options
} = {}
) {
const source = axios.CancelToken.source();
const promise = this.client({
url,
cancelToken: source.token,
...options,
}).catch((err) => {
if (!retry) {
throw err;
}
return new Promise((resolve) => {
setTimeout(resolve, retryDelay);
}).then(() =>
this.request(url, {
...options,
retryDelay: retryDelay * retryDelayFactor,
retry: retry - 1,
})
);
});
const cancel = () => {
source.cancel();
};
promise.cancel = cancel;
if (Number.isInteger(this.timeout) || Number.isInteger(timeout)) {
setTimeout(cancel, this.timeout || timeout);
}
return promise;
}
}
/**
* Retry promise before rejected
*
* @param {Function} fn - function return a promise
* @param {Object} [options] - options
* @param {number} [options.maxRetries=10] - max retries before rejected
* @param {number} [options.retriesDelay=100] - ms for delay before next retry
* @param {number} [options.retriesDelayFactor=1] - factor for increase next retries delay
*
* @returns {Promise}
*/
export function retryPromise(
fn,
{ maxRetries = 10, retriesDelay = 100, retriesDelayFactor = 1 } = {}
) {
return fn().catch((err) => {
if (!maxRetries) {
throw err;
}
return new Promise((resolve) => {
setTimeout(resolve, retriesDelay);
}).then(() => retry(fn, maxRetries - 1, retriesDelay * retriesDelayFactor));
});
}
/**
* Retry promise before rejected
*
* @param {Function} fn - function return a promise
* @param {Object} [options] - options
* @param {number} [options.maxRetries=10] - max retries before rejected
* @param {number} [options.retriesDelay=100] - delay before next retry
* @param {number} [options.retriesDelayFactor=1] - factor for increase next retries delay
*
* @returns {Promise}
*/
export async function retryAsync(
fn,
{ maxRetries = 10, retriesDelay = 100, retriesDelayFactor = 1 } = {}
) {
try {
return await fn();
} catch (err) {
if (!maxRetries) {
throw err;
}
await new Promise((resolve) => setTimeout(resolve, retriesDelay));
return retry(fn, maxRetries - 1, retriesDelay * retriesDelayFactor);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment