@supercat1337/fetcher
v2.0.1
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, and full TypeScript support.
Features
- ✅ Cancellation – abort ongoing requests at any level.
- ✅ Smart retries – retry only on temporary failures (network errors, 5xx). Customizable via
shouldRetry. - ✅ Singleton fetcher – automatically cancel previous request when a new one starts.
- ✅ Fetcher manager – create multiple retry+singleton fetchers, cancel all at once.
- ✅ Memory safe – automatic listener cleanup, no leaks.
- ✅ Full TypeScript – via JSDoc, no compilation needed.
- ✅ Zero dependencies (except tiny
@supercat1337/event-emitter).
Installation
npm install @supercat1337/fetcherQuick Start
Basic retry fetch
import { createRetryFetch } from '@supercat1337/fetcher';
const fetchWithRetry = createRetryFetch({ retryCount: 3, waitTime: 1000 });
try {
const response = await fetchWithRetry('https://api.example.com/data');
const data = await response.json();
console.log(data);
} catch (err) {
console.error('Request failed after retries', err);
}Singleton fetch (auto‑cancel previous)
import { createSingletonFetch } from '@supercat1337/fetcher';
const fetchSingleton = createSingletonFetch();
// Fast consecutive clicks – only the last request succeeds
fetchSingleton('/api/search?q=hello');
fetchSingleton('/api/search?q=world'); // cancels the first oneFull‑featured Fetcher manager
import { Fetcher } from '@supercat1337/fetcher';
const fetcher = new Fetcher();
const { fetch: fetchUsers } = fetcher.createFetchFunction({ retryCount: 2 });
const { fetch: fetchPosts } = fetcher.createFetchFunction({ retryCount: 2 });
// Cancel everything at once
document.getElementById('cancelBtn').onclick = () => fetcher.cancel();
// Manual cleanup of a specific fetcher
const { fetch, unsubscribe } = fetcher.createFetchFunction();
// later: unsubscribe();API Reference
createRetryFetch(options)
| Option | Type | Default | Description |
| -------------- | --------------------------------------- | ------------------ | ------------------------------------------------------------------------------ |
| retryCount | number | 3 | Max retry attempts (≥0) |
| waitTime | number | 1000 | Delay between retries (ms) |
| shouldRetry | (error: Error \| Response) => boolean | see below | Custom retry predicate. Default: retry on network errors and HTTP status ≥500. |
| customFetch | FetchFunction | globalThis.fetch | Alternative fetch implementation |
| eventEmitter | EventEmitter | new instance | For external cancellation |
Returns (resource, options) => Promise<Response>.
createSingletonFetch(customFetch?)
Returns a fetch function that cancels any previous pending request made with it.
class SingletonFetcher
Low‑level class with same behaviour, exposes fetch(), cancel(), and is_loading.
class Fetcher
createFetchFunction(options?)→ returns{ fetch, cancel, unsubscribe }fetch(resource, options?)→ one‑off cancellable fetch (listens toFetcher.cancel())cancel()→ aborts all ongoing fetches created by this instancedestroy()→ clears all listeners (call when you no longer need the instance)
Advanced Usage
Custom retry logic
const fetchWithRetry = createRetryFetch({
retryCount: 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 fetchFn = createSingletonFetch();
const promise = fetchFn('/api/long-task', { signal: controller.signal });
controller.abort(); // cancels the requestMemory cleanup
const fetcher = new Fetcher();
const { fetch, unsubscribe } = fetcher.createFetchFunction();
// When component unmounts:
unsubscribe(); // removes internal listener
// or globally:
fetcher.destroy(); // cleans up all created fetchersTypeScript support
The package is fully typed via JSDoc. In a TypeScript project, you get autocompletion and type checking without any extra configuration.
// TypeScript will infer argument types
import { createRetryFetch } from '@supercat1337/fetcher';
const fetch = createRetryFetch({ retryCount: 2 });
const response = await fetch('https://api.example.com'); // ResponseIf you need custom types, import from the package:
import type { FetchFunction, RetryFetchOptions } from '@supercat1337/fetcher';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) |
| Node.js 16 | ⚠️ Works if you provide a custom fetch (e.g., node-fetch) and include our AbortSignal.any polyfill |
Running examples locally
Clone the repository and run any example:
git clone https://github.com/supercat1337/fetcher.git
cd fetcher
npm install
npx serve examples/Fetcher # or retryFetch, singletonFetcherThen open the displayed URL.
