A tiny utility for retrying asynchronous or synchronous operations with customizable options such as retry limits, delays, exponential backoff, and cancellation.
Add this module to your deno project:
deno add @deleteme/retry-asyncAdd this module to your Node.js project using npm or yarn:
npx jsr add @deleteme/retry-asyncyarn dlx jsr add @deleteme/retry-asyncimport { retry } from "@deleteme/retry-async";Retries a given operation until it succeeds, reaches the maximum number of retries, or is aborted.
function retry<T>(
operation: Operation,
options?: RetryOptions,
): Promise<T>;-
operation:
A function to be retried. It can be either synchronous or asynchronous.type Operation = ( options?: { abortSignal?: AbortSignal }, ) => any | Promise<any>;
-
options(optional):
An object to configure the retry behavior.interface RetryOptions { maxRetries?: number; // Maximum number of retries (default: 3) retryDelay?: number; // Delay between retries in milliseconds (default: 1000) decay?: number | DecayFunction; // Exponential backoff factor or custom decay function abortSignal?: AbortSignal; // Signal to cancel the retry process onBeforeRetry?: ( onBeforeRetryArg: { retries: number; rejection: any }, ) => Promise<void> | void; // Callback invoked after each retry timeout?: number; // Maximum time in milliseconds before the operation times out }
A Promise that resolves with the result of the operation or rejects with the
last error encountered.
- The
operationis called repeatedly until it resolves successfully or the retry limit is reached. - If
retryDelayis provided, the function waits for the specified delay between retries. - If
decayis provided:- If it's a number greater than 1, the delay increases exponentially.
- If it's a function, it calculates the delay based on the number of retries and the initial delay.
- If
abortSignalis provided and aborted, the retry process is canceled immediately. - If
timeoutis provided, the retry process will reject with aTimeoutErrorif the total time exceeds the specified duration. - The
onBeforeRetrycallback is invoked after each failed attempt, providing details about the retry.
import { retry } from "@deleteme/retry-async";
async function fetchData() {
const result = await retry(async () => {
const response = await fetch("https://example.com/api");
if (!response.ok) throw new Error("Request failed");
return response.json();
});
console.log(result);
}import { retry } from "@deleteme/retry-async";
async function fetchData() {
const result = await retry(async () => {
const response = await fetch("https://example.com/api");
if (!response.ok) throw new Error("Request failed");
return response.json();
}, {
maxRetries: 5,
retryDelay: 2000,
decay: 2, // Exponential backoff
onBeforeRetry: ({ retries, rejection }) => {
console.log(`Retry #${retries} failed:`, rejection);
},
});
console.log(result);
}import { retry } from "@deleteme/retry-async";
const controller = new AbortController();
setTimeout(() => controller.abort(), 5000); // Abort after 5 seconds
try {
const result = await retry(async ({ abortSignal }) => {
const response = await fetch("https://example.com/api", {
// The abort signal is also passed to this operation function.
// Ensure the signal is sent to fetch so that it may also abort the request.
signal: abortSignal,
});
if (!response.ok) throw new Error("Request failed");
return response.json();
}, {
abortSignal: controller.signal,
});
console.log(result);
} catch (error) {
console.error("Operation aborted:", error);
}import { retry } from "@deleteme/retry-async";
try {
const result = await retry(async () => {
const response = await fetch("https://example.com/api");
if (!response.ok) throw new Error("Request failed");
return response.json();
}, {
timeout: 3000, // Timeout after 3 seconds
});
console.log(result);
} catch (error) {
console.error("Operation timed out:", error);
}Resolves after a specified number of milliseconds. Supports an abort signal to cancel.
import { delay } from "@deleteme/retry-async";
await delay(1000, { abortSignal }); // Wait for 1 secondThis project is licensed under the MIT License.