@supercat1337/fetcher
v3.0.0
Published
Advanced fetch utility with cancellation, smart retry with error filtering, singleton requests, and full TypeScript support.
Maintainers
Readme
@supercat1337/fetcher
Advanced fetch utility with cancellation, smart retries, singleton requests, XHR progress, and full TypeScript support.
Features
- ✅ Cancellation – abort ongoing requests at any level using standard
AbortController. - ✅ Smart retries – retry only on temporary failures (network errors, 5xx). Customizable via
shouldRetry. - ✅ Singleton fetcher – automatically cancel previous request when a new one starts.
- ✅ XHR with progress – upload/download progress, timeouts, and retries.
- ✅ Fetcher manager – create multiple retry+singleton fetchers, cancel all at once.
- ✅ Memory safe – automatic cleanup via
AbortController, no listeners to leak. - ✅ Full TypeScript – via JSDoc, no compilation needed.
- ✅ Zero dependencies – uses only native browser/Node.js APIs.
Installation
npm install @supercat1337/fetcherQuick Start
Basic retry fetch (native)
import { createRetryFetch } from '@supercat1337/fetcher';
const fetchWithRetry = createRetryFetch({ maxAttempts: 3, waitTime: 1000 });
try {
const response = await fetchWithRetry('https://api.example.com/data');
const data = await response.json();
} catch (err) {
console.error('Failed after 3 attempts', err);
}Singleton fetch (auto‑cancel previous)
import { createSingletonFetch } from '@supercat1337/fetcher';
const fetchSingleton = createSingletonFetch();
fetchSingleton('/api/search?q=hello');
fetchSingleton('/api/search?q=world'); // cancels the first oneXHR with upload progress and retries
import { createRetryXhr } from '@supercat1337/fetcher';
const upload = createRetryXhr({ maxAttempts: 3, waitTime: 2000 });
const response = await upload('https://api.example.com/upload', {
method: 'POST',
body: fileData,
onUploadProgress: (loaded, total) => console.log(`${loaded}/${total}`),
onProgress: (loaded, total) => console.log(`Download: ${loaded}/${total}`),
});Full‑featured Fetcher manager with XHR support
import { Fetcher } from '@supercat1337/fetcher';
const fetcher = new Fetcher();
const { fetch: fetchUsers } = fetcher.createFetchFunction({ maxAttempts: 2 });
const { fetch: uploadFile } = fetcher.createXhrFetchFunction({ maxAttempts: 3 });
// Cancel everything at once
document.getElementById('cancelBtn').onclick = () => fetcher.cancel();
// Clean up when done
fetcher.destroy();Composing retry and singleton manually
import { withRetry, SingletonFetcher, xhrFetch } from '@supercat1337/fetcher';
const retryXhr = withRetry(xhrFetch, { maxAttempts: 3 });
const singleton = new SingletonFetcher(retryXhr);
const response = await singleton.fetch('/data', { onProgress: p => console.log(p) });API Reference
withRetry(fetcher, options)
| Option | Type | Default | Description |
| ------------- | --------------------------------------- | --------- | ----------------------------------------------------------- |
| maxAttempts | number | 3 | Total attempts (including first) |
| waitTime | number | 1000 | Delay between retries (ms) |
| shouldRetry | (error: Error \| Response) => boolean | see below | Custom predicate. Default: retry on network errors and 5xx. |
Returns a function with the same signature as fetcher.
createRetryFetch(options?)
Same as withRetry(fetch, options).
createRetryXhr(options?)
Same as withRetry(xhrFetch, options).
createSingletonFetch(customFetch?)
Returns a singleton fetch function using native fetch (or custom fetch).
createSingletonXhr()
Returns a singleton fetch function using xhrFetch (progress supported).
createSingletonRetryXhr(retryOptions?)
Returns a singleton + retry function using xhrFetch.
class SingletonFetcher
constructor(customFetch?)fetch(resource, options): Promise<Response>cancel(): voidcancelAndWait(): Promise<void>isLoading: boolean(getter)
class Fetcher
createFetchFunction(options?)→{ fetch, cancel, cancelAndWait }(native fetch)createXhrFetchFunction(options?)→{ fetch, cancel, cancelAndWait }(XHR with progress)fetch(resource, options?)– one‑off cancellable fetch (native)cancel()– cancels all ongoing fetches created by this instancedestroy()– aborts all requests and cleans up
Advanced Usage
Custom retry predicate
const fetchWithRetry = createRetryFetch({
maxAttempts: 3,
shouldRetry: err => {
if (err instanceof Response) return err.status === 429; // rate limit
return err.code === 'ECONNRESET';
},
});Using with AbortController
const controller = new AbortController();
const fetchSingleton = createSingletonFetch();
const promise = fetchSingleton('/api/long-task', { signal: controller.signal });
controller.abort(); // cancels the requestMemory cleanup
const fetcher = new Fetcher();
const { fetch } = fetcher.createFetchFunction();
// When you no longer need this fetcher:
fetcher.destroy(); // aborts all ongoing requests and releases resourcesTypeScript support
The package is fully typed via JSDoc. In a TypeScript project, you get autocompletion and type checking without extra configuration.
import { createRetryXhr, type XhrFetchOptions } from '@supercat1337/fetcher';
const fetch = createRetryXhr({ maxAttempts: 3 });
const response = await fetch('/api', {
onProgress: (loaded, total) => console.log(loaded, total),
} as XhrFetchOptions);Error handling
- Network errors and failed responses are caught and passed to
shouldRetry. - If all retries fail, the original error is thrown.
- Cancellation throws a
DOMExceptionwithname = "AbortError".
Browser / Node support
| Environment | Support | | --------------- | ---------------------------------------------------- | | Modern browsers | ✅ (Chrome 85+, Firefox 88+, Safari 15.4+, Edge 85+) | | Node.js | ✅ 18+ (native fetch + AbortSignal.any) |
No polyfills are included. For older environments, provide your own
AbortSignal.anypolyfill.
