retry
Retry an asynchronous function with exponential backoff on failure.
Signature
typescript
function retry<T>(
fn: () => Promise<T>,
options?: {
times?: number;
delay?: number;
backoff?: number | ((attempt: number, delay: number) => number);
retryDelay?: (attempt: number) => number;
shouldRetry?: (error: unknown, attempt: number) => boolean;
signal?: AbortSignal;
},
): Promise<T>;Parameters
fn– The asynchronous function to retryoptions.times– Total number of attempts including the first (default:3)options.delay– Delay in milliseconds between retries (default:250). Ignored whenretryDelayis providedoptions.backoff– Exponential backoff factor or custom function (default:1, no backoff). Ignored whenretryDelayis providedoptions.retryDelay– Per-attempt delay function.attemptis 0-based (0 = before the 2nd try). Supersedesdelayandbackoffoptions.shouldRetry– Returnfalseto stop retrying for a specific error.attemptis the 0-based failure countoptions.signal–AbortSignalto cancel retries; throws the signal'sreasonon abort
Returns
The result of the asynchronous function.
Examples
Basic Usage
typescript
import { retry } from '@vielzeug/toolkit';
const result = await retry(() => fetchData(), { times: 3, delay: 1000 });Exponential Backoff
typescript
import { retry } from '@vielzeug/toolkit';
const result = await retry(() => unreliableAPICall(), {
times: 5,
delay: 500,
backoff: 2, // Delays: 500ms, 1000ms, 2000ms, 4000ms
});Per-Attempt Delay Override (retryDelay)
Use retryDelay for full control over each inter-attempt delay. It supersedes delay and backoff.
typescript
import { retry } from '@vielzeug/toolkit';
// Capped exponential backoff: 1s, 2s, 4s, 8s (max 30s)
const result = await retry(() => fetchData(), {
times: 5,
retryDelay: (attempt) => Math.min(1000 * 2 ** attempt, 30_000),
});Selective Retry with shouldRetry
Return false to abort retries for a specific error type.
typescript
import { retry } from '@vielzeug/toolkit';
const result = await retry(() => fetchUser(id), {
times: 3,
delay: 500,
// Never retry 4xx client errors — only retry 5xx / network failures
shouldRetry: (err, attempt) => {
if (err instanceof Response && err.status >= 400 && err.status < 500) return false;
return true;
},
});With AbortSignal
typescript
import { retry } from '@vielzeug/toolkit';
const controller = new AbortController();
const result = await retry(() => fetchData(), {
times: 3,
delay: 1000,
signal: controller.signal,
});
// Can abort from outside
controller.abort();Custom Backoff Function
typescript
import { retry } from '@vielzeug/toolkit';
const result = await retry(() => fetchData(), {
times: 4,
delay: 1000,
backoff: (attempt, delay) => delay * attempt, // Linear backoff
});Robust API Call
typescript
import { retry } from '@vielzeug/toolkit';
async function fetchWithRetry(url: string) {
return retry(
async () => {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return response.json();
},
{
times: 3,
retryDelay: (attempt) => Math.min(1000 * 2 ** attempt, 30_000),
shouldRetry: (err) => !(err instanceof Error && err.message.startsWith('HTTP 4')),
},
);
}Related
- attempt – Execute with error handling and retry