Skip to content

API & options

Signature

ts
retry<T>(fn: (attempt: number, signal?: AbortSignal) => Promise<T>, options?: Options): Promise<T>;

Calls fn with the current 1-indexed attempt number (1 on the first try, 2 on the first retry, …) and, where AbortController is available, a per-attempt AbortSignal. If the returned promise resolves, retry resolves with that value (unless until keeps polling). If it rejects, retry waits and calls fn again, up to times retries.

It stops when the retries are exhausted, shouldRetry returns false, the budget (maxElapsedTime) is spent, the signal aborts, or fn throws a BailError.

Options

OptionTypeDefaultDescription
timesnumber1Retries after the first failure.
initialDelayTimenumber100Delay before the first retry, in ms.
backoffFactornumber2Multiplier applied to the delay each retry.
maxDelayTimenumberInfinityUpper bound on the delay between attempts, in ms.
jitterboolean | 'equal' | 'full'falseRandomise each delay. 'equal'/true[delay/2, delay]; 'full'[0, delay].
foreverbooleanfalseRetry indefinitely until success or abort, ignoring times.
attemptTimeoutnumberInfinityAbort and retry a single attempt that runs longer than this, in ms.
maxElapsedTimenumberInfinityStop retrying once this much wall-clock time has elapsed, in ms.
getDelay(error, ctx) => number | nullnullDerive the next wait from the error; return ms to override or null to keep the backoff.
until(result) => booleannullRetry while the resolved value fails this predicate (polling).
signalAbortSignalundefinedCancel pending retries.
onRetry(error, options) => voidnullCalled on each retry — for logging and metrics.
shouldRetry(error) => booleannullReturn false to stop retrying immediately.

getDelay's context is { attempt: number; computedDelay: number }.

Returns

Promise<T> — resolves with whatever fn resolves to (or the last value when until runs out), and rejects with the last error (or the abort reason, or a BailError's cause).

Errors & values

ts
import retry, { BailError, AttemptTimeoutError } from 'promise-fn-retry';
  • BailError — throw new BailError(cause) from fn to give up immediately; the retry rejects with cause.
  • AttemptTimeoutError — the error a timed-out attempt rejects with (it flows through shouldRetry/onRetry).

Exported types

ts
import type {
  Options,
  ResolvedOptions,
  OnRetry,
  ShouldRetry,
  Jitter,
  OperationFn,
  GetDelay,
  Until,
} from 'promise-fn-retry';

How the delay is calculated

Each retry multiplies the previous delay by backoffFactor, starting from initialDelayTime; the result is clamped to maxDelayTime, randomised by jitter, and finally overridden by getDelay (if any) and trimmed to fit maxElapsedTime.

RetryDelay (defaults)
1st100 ms
2nd200 ms
3rd400 ms
4th800 ms

See it on the Playground.