UNPKG

@tanstack/query-core

Version:

The framework agnostic core that powers TanStack Query

137 lines 3.58 kB
// src/retryer.ts import { focusManager } from "./focusManager.js"; import { onlineManager } from "./onlineManager.js"; import { isServer, sleep } from "./utils.js"; function defaultRetryDelay(failureCount) { return Math.min(1e3 * 2 ** failureCount, 3e4); } function canFetch(networkMode) { return (networkMode ?? "online") === "online" ? onlineManager.isOnline() : true; } var CancelledError = class { constructor(options) { this.revert = options?.revert; this.silent = options?.silent; } }; function isCancelledError(value) { return value instanceof CancelledError; } function createRetryer(config) { let isRetryCancelled = false; let failureCount = 0; let isResolved = false; let continueFn; let promiseResolve; let promiseReject; const promise = new Promise((outerResolve, outerReject) => { promiseResolve = outerResolve; promiseReject = outerReject; }); const cancel = (cancelOptions) => { if (!isResolved) { reject(new CancelledError(cancelOptions)); config.abort?.(); } }; const cancelRetry = () => { isRetryCancelled = true; }; const continueRetry = () => { isRetryCancelled = false; }; const shouldPause = () => !focusManager.isFocused() || config.networkMode !== "always" && !onlineManager.isOnline(); const resolve = (value) => { if (!isResolved) { isResolved = true; config.onSuccess?.(value); continueFn?.(); promiseResolve(value); } }; const reject = (value) => { if (!isResolved) { isResolved = true; config.onError?.(value); continueFn?.(); promiseReject(value); } }; const pause = () => { return new Promise((continueResolve) => { continueFn = (value) => { const canContinue = isResolved || !shouldPause(); if (canContinue) { continueResolve(value); } return canContinue; }; config.onPause?.(); }).then(() => { continueFn = void 0; if (!isResolved) { config.onContinue?.(); } }); }; const run = () => { if (isResolved) { return; } let promiseOrValue; try { promiseOrValue = config.fn(); } catch (error) { promiseOrValue = Promise.reject(error); } Promise.resolve(promiseOrValue).then(resolve).catch((error) => { if (isResolved) { return; } const retry = config.retry ?? (isServer ? 0 : 3); const retryDelay = config.retryDelay ?? defaultRetryDelay; const delay = typeof retryDelay === "function" ? retryDelay(failureCount, error) : retryDelay; const shouldRetry = retry === true || typeof retry === "number" && failureCount < retry || typeof retry === "function" && retry(failureCount, error); if (isRetryCancelled || !shouldRetry) { reject(error); return; } failureCount++; config.onFail?.(failureCount, error); sleep(delay).then(() => { if (shouldPause()) { return pause(); } return; }).then(() => { if (isRetryCancelled) { reject(error); } else { run(); } }); }); }; if (canFetch(config.networkMode)) { run(); } else { pause().then(run); } return { promise, cancel, continue: () => { const didContinue = continueFn?.(); return didContinue ? promise : Promise.resolve(); }, cancelRetry, continueRetry }; } export { CancelledError, canFetch, createRetryer, isCancelledError }; //# sourceMappingURL=retryer.js.map