Skip to content

retry

Edit

Repeats a failing operation until it succeeds or reaches an attempt limit.

retry.ts
export type RetryOptions = {
maxAttempts?: number;
delayMs?: number;
shouldRetry?: (
this: void,
error: unknown,
failedAttempt: number
) => boolean | PromiseLike<boolean>;
};
/** Repeats a failing operation until it succeeds or reaches the attempt limit. */
export const retry = async <Return>(
operation: (this: void, attempt: number) => Return,
{
maxAttempts = 3,
delayMs = 0,
shouldRetry,
}: RetryOptions = {}
): Promise<Awaited<Return>> => {
if (!Number.isSafeInteger(maxAttempts) || maxAttempts < 1) {
throw new RangeError("maxAttempts must be a positive safe integer");
}
if (!Number.isFinite(delayMs) || delayMs < 0) {
throw new RangeError("delayMs must be a finite, non-negative number");
}
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
try {
return await operation(attempt);
} catch (error) {
const isLastAttempt = attempt === maxAttempts;
if (isLastAttempt || (shouldRetry && !(await shouldRetry(error, attempt)))) {
throw error;
}
if (delayMs > 0) {
await new Promise<void>((resolve) => setTimeout(resolve, delayMs));
}
}
}
throw new Error("retry reached an unreachable state");
};
Terminal
wget -O src/lib/retry.ts https://raw.githubusercontent.com/jrTilak/lazykit/HEAD/registry/functions/retry.ts
retry.example.ts
import { retry } from "./retry";
const result = await retry(
async (attempt) => {
console.log("Attempt:", attempt);
if (attempt < 3) throw new Error("Failed to fetch data");
return "Data fetched successfully";
},
{ maxAttempts: 3, delayMs: 1_000 }
);
console.log(result);
  • operation ((attempt: number) => T | PromiseLike<T>) — Work to run. attempt starts at 1.
  • options.maxAttempts (number, default: 3) — Total number of allowed attempts.
  • options.delayMs (number, default: 0) — Delay between failed attempts.
  • options.shouldRetry ((error, failedAttempt) => boolean | Promise<boolean>) — Optional decision function that can stop retrying early.

Promise<Awaited<T>> — The first successful value. The final operation error is thrown when retrying stops.