45 lines
1.4 KiB
JavaScript
45 lines
1.4 KiB
JavaScript
|
|
import { delay } from "../promise/delay.mjs";
|
||
|
|
//#region src/function/retry.ts
|
||
|
|
const DEFAULT_DELAY = 0;
|
||
|
|
const DEFAULT_RETRIES = Number.POSITIVE_INFINITY;
|
||
|
|
const DEFAULT_SHOULD_RETRY = () => true;
|
||
|
|
/**
|
||
|
|
* Retries a function that returns a promise with specified options.
|
||
|
|
*
|
||
|
|
* @template T
|
||
|
|
* @param {() => Promise<T>} func - The function to retry. It should return a promise.
|
||
|
|
* @param {number | RetryOptions} [_options] - Either the number of retries or an options object.
|
||
|
|
* @returns {Promise<T>} A promise that resolves with the value of the successful function call.
|
||
|
|
*/
|
||
|
|
async function retry(func, _options) {
|
||
|
|
let delay$1;
|
||
|
|
let retries;
|
||
|
|
let signal;
|
||
|
|
let shouldRetry;
|
||
|
|
if (typeof _options === "number") {
|
||
|
|
delay$1 = DEFAULT_DELAY;
|
||
|
|
retries = _options;
|
||
|
|
signal = void 0;
|
||
|
|
shouldRetry = DEFAULT_SHOULD_RETRY;
|
||
|
|
} else {
|
||
|
|
delay$1 = _options?.delay ?? DEFAULT_DELAY;
|
||
|
|
retries = _options?.retries ?? DEFAULT_RETRIES;
|
||
|
|
signal = _options?.signal;
|
||
|
|
shouldRetry = _options?.shouldRetry ?? DEFAULT_SHOULD_RETRY;
|
||
|
|
}
|
||
|
|
let error;
|
||
|
|
for (let attempts = 0; attempts <= retries; attempts++) {
|
||
|
|
if (signal?.aborted) throw error ?? /* @__PURE__ */ new Error(`The retry operation was aborted due to an abort signal.`);
|
||
|
|
try {
|
||
|
|
return await func();
|
||
|
|
} catch (err) {
|
||
|
|
error = err;
|
||
|
|
if (!shouldRetry(err, attempts)) throw err;
|
||
|
|
await delay(typeof delay$1 === "function" ? delay$1(attempts) : delay$1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
throw error;
|
||
|
|
}
|
||
|
|
//#endregion
|
||
|
|
export { retry };
|