UNPKG

async-wrappers

Version:

A set of wrapper functions to perform debouncing, throttling, retrying etc.

235 lines (197 loc) 5.02 kB
import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator"; import wait from './wait'; /** * @internal */ var defaultDelays = [// 10 seconds 10 * 1000, // 1 Minute 60 * 1000, // 5 Minutes 5 * 60 * 1000, // 10 Minutes 10 * 60 * 1000]; /** * Function for determining a how long to wait after the given attempt * * @category Retry */ /** * @internal */ var getDelayFn = times => { if (typeof times === 'function') { return times; } if (typeof times === 'number') { return () => times; } return attempt => times[Math.min(attempt, times.length - 1)]; }; /** * A function used to determine if to stop for the given retry attempt. * * Errors thrown by this function will cause retry to reject with the * errorTypes of retry errors * * @category Retry */ /** * @internal */ var getStopFn = stop => { if (typeof stop === 'function') { return stop; } return attempt => attempt >= stop; }; /** * callback for [[retry]] to determine the arguments to * the function to retry. * @typeparam RetryFunction the type of function to retry. * * @category Retry */ /** * @internal */ var getArgsFn = args => { if (typeof args === 'function') { return args; } return () => args; }; /** * Types of retry errors * * @category Retry */ /** * Base Class for all retry errors * * @category Retry */ export class RetryError extends Error { /** * The type of error */ /** * The last error that occurred when retrying */ constructor(type, message, error) { super(message); this.type = type; this.error = error; } } /** * The error given when retrying is cancelled * * @category Retry */ export class RetryCancelledError extends RetryError { constructor() { var message = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'Cancelled'; var error = arguments.length > 1 ? arguments[1] : undefined; super('cancelled', message, error); } } /** * The error given when retrying stops * * @category Retry */ export class RetryStoppedError extends RetryError { constructor() { var message = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'Stopped'; var error = arguments.length > 1 ? arguments[1] : undefined; super('stopped', message, error); } } /** * The return type of [[retry]] * * @category Retry */ /** * Retry the wrapped function according to the * * @param func the function to retry. * @param delay a delay in milliseconds, an array of millisecond delays or * [[RetryDelayCallback|callback]] to determine the delay before the next * attempt. * * @param stop the number of attempts, or [[RetryStopCallback|callback]] to * determine when retry should stop retrying `func`. * @param args an array or [[RetryArgumentsCallback|callback]] to * provide arguments to `func` * * @category Wrapper */ var retry = function retry(func) { var delay = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : defaultDelays; var stop = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 10; var args = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : []; var getNextDelay = getDelayFn(delay); var shouldStop = getStopFn(stop); var getArgs = getArgsFn(args); var attempt = 0; var finished = false; var cancelled = false; var cancelReason; var waiting; var previousDelay = 0; var currentError; var afterAwait = () => { if (finished || !cancelled) { return; } throw new RetryCancelledError(cancelReason, currentError); }; var exec = /*#__PURE__*/ function () { var _ref = _asyncToGenerator(function* () { while (!cancelled) { var _args = yield getArgs(attempt, previousDelay, currentError); afterAwait(); try { var value = yield func(..._args); finished = true; return value; } catch (error) { currentError = error; afterAwait(); // how long to wait after the last attempt var _delay = yield getNextDelay(attempt, previousDelay, error); afterAwait(); previousDelay = _delay; attempt++; var _stop = yield shouldStop(attempt, _delay, error); afterAwait(); // should we stop the next attempt? if (_stop) { var _reason = typeof _stop === 'string' ? _stop : undefined; finished = true; throw new RetryStoppedError(_reason, error); } waiting = wait(_delay); yield waiting; waiting = undefined; afterAwait(); } } }); return function exec() { return _ref.apply(this, arguments); }; }(); var result = exec(); result.cancel = reason => { if (finished || cancelled) { return; } cancelled = true; cancelReason = reason; if (waiting) { waiting.stop(); } }; return result; }; export default retry;