Async utilities for managing concurrency, retries, queues, and rate limiting
The @temelj/async package provides a comprehensive set of utilities for working with asynchronous operations in TypeScript. It includes concurrency control, retry logic, rate limiting, synchronization primitives, and error handling.
Retries a function upon failure with configurable backoff.
function retry<T>( fn: (attempt: number) => Promise<T>, options?: RetryOptions,): Promise<T>
RetryOptions interface
interface RetryOptions extends StandardOptions { /** Maximum number of attempts. Default: 3. */ times?: number; /** Delay between retries in ms, or a function computing the delay from the attempt number. */ delay?: number | ((attempt: number) => number); /** Predicate to decide whether to retry on a given error. */ shouldRetry?: (error: unknown) => boolean;}
import { limit } from "@temelj/async";const limitedFetch = limit(fetch, 3);// Only 3 requests will run concurrentlyconst results = await Promise.all([ limitedFetch("url1"), limitedFetch("url2"), limitedFetch("url3"), limitedFetch("url4"), // Waits for one to complete limitedFetch("url5"), // Waits for one to complete]);
interface DebounceOptions { /** Fire on the leading edge. Default: false. */ leading?: boolean; /** Fire on the trailing edge. Default: true. */ trailing?: boolean; /** Optional AbortSignal to cancel debouncing. */ signal?: AbortSignal;}
import { debounce } from "@temelj/async";const debouncedSearch = debounce(async (query: string) => { return await api.search(query);}, 300);// Only the last call within 300ms will executedebouncedSearch("a");debouncedSearch("ab");debouncedSearch("abc"); // Only this one executes
import { throttle } from "@temelj/async";const throttledScroll = throttle(async () => { await updateScrollPosition();}, 100);// Will execute at most once every 100mswindow.addEventListener("scroll", throttledScroll);
A synchronization barrier that waits until a specified number of tasks have called wait. Once the capacity is reached, all waiting tasks are released simultaneously.
class Barrier { constructor(capacity: number) wait(signal?: AbortSignal): Promise<void>}
import { Barrier } from "@temelj/async";const barrier = new Barrier(3);async function worker(id: number) { console.log(`Worker ${id} starting`); await doWork(); console.log(`Worker ${id} waiting at barrier`); await barrier.wait(); console.log(`Worker ${id} released`);}// All workers wait until 3 have reached the barrierPromise.all([worker(1), worker(2), worker(3)]);
interface ResilienceOptions extends StandardOptions { /** If true, the operation fails immediately on the first error. Default: true. */ stopOnError?: boolean;}