FastFetch is a smarter fetch()
wrapper that adds auto-retry and request deduplication to standard HTTP requests, reducing boilerplate and increasing resilience. It is designed to work seamlessly in both Node.js and browser environments using modern ES modules.
Currently live on NPM at https://www.npmjs.com/package/@hoangsonw/fast-fetch. This package is a work in progress, and we welcome contributions and feedback!
Note: Currently, FastFetch does not support caching. For caching, consider using GhostCache in conjunction with FastFetch :)
- Features
- Installation
- Usage
- API Reference
- Configuration Options
- Advanced Examples
- Testing
- Demo Script
- License
- Contributing
- Auto-Retry: Automatically retries failed HTTP requests with configurable delay and retry count.
- Request Deduplication: Merges multiple identical in-flight requests into a single network call.
- Minimal Boilerplate: Wraps the native
fetch()
function with enhanced functionality. - TypeScript Support: Fully written in TypeScript with complete type definitions.
- ESM Compatible: Compiled using NodeNext module resolution for seamless ESM integration.
- Node.js v14 or higher
- npm v6 or higher
npm install @hoangsonw/fast-fetch
yarn add @hoangsonw/fast-fetch
FastFetch can be used as a drop-in replacement for the native fetch()
function with additional options.
Below is a simple example that uses FastFetch to make an API call and print the results:
import { fastFetch } from "@hoangsonw/fast-fetch";
fastFetch("https://pokeapi.co/api/v2/pokemon/ditto")
.then((res) => res.json())
.then((data) => {
console.log("Fetched data:", data);
})
.catch((err) => console.error("Fetch error:", err));
FastFetch supports auto-retry and deduplication through additional options. For example, you can automatically retry up to 2 times with a delay of 2000ms between attempts, and deduplicate in-flight requests:
import { fastFetch } from "@hoangsonw/fast-fetch";
fastFetch("https://pokeapi.co/api/v2/pokemon/ditto", {
retries: 2,
retryDelay: 2000,
deduplicate: true,
shouldRetry: (errorOrResponse, attempt) => {
console.log(`Retry attempt #${attempt}`);
// If response exists and status is 5xx, retry
if (errorOrResponse instanceof Response) {
return errorOrResponse.status >= 500;
}
// For network errors or other errors, retry
return true;
},
})
.then((res) => res.json())
.then((data) => console.log("FastFetch data:", data))
.catch((err) => console.error("FastFetch error:", err));
FastFetch can deduplicate in-flight requests even when used alongside Axios by registering an Axios instance. This means if multiple identical requests are made concurrently via Axios, only one network call is performed.
import axios from "axios";
import { fastFetch, registerAxios } from "@hoangsonw/fast-fetch";
// Create an Axios instance
const api = axios.create({ baseURL: "https://pokeapi.co/api/v2" });
// Register the Axios instance with FastFetch
registerAxios(api);
api
.get("/pokemon/ditto")
.then((response) => {
console.log("Axios fetched data:", response.data);
})
.catch((error) => {
console.error("Axios error:", error);
});
-
Parameters:
input
: URL or Request object.init
: An object that extends standardRequestInit
with additional options:retries
: number — Number of retry attempts (default:0
).retryDelay
: number — Delay in milliseconds between retries (default:1000
).deduplicate
: boolean — Whether to deduplicate in-flight requests (default:true
).shouldRetry
: function — A custom function(errorOrResponse: Response | Error, attempt: number) => boolean
that determines whether to retry based on error or response status.
-
Returns:
APromise
that resolves to aResponse
object.
-
registerAxios(instance: AxiosInstance): void
Registers an Axios instance so that FastFetch can deduplicate in-flight requests for Axios as well. -
Other functions:
FastFetch only wraps the nativefetch()
and does not cache responses (use GhostCache if caching is required).
- retries: Number of times to retry the fetch on failure.
- retryDelay: Delay (in milliseconds) before retrying.
- deduplicate: When set to
true
, identical in-flight requests are deduplicated. - shouldRetry: Custom function to decide whether to retry a request based on error or response.
Implement custom logic to only retry on specific HTTP status codes:
import { fastFetch } from "@hoangsonw/fast-fetch";
fastFetch("https://example.com/api/data", {
retries: 3,
retryDelay: 1500,
shouldRetry: (errorOrResponse, attempt) => {
if (errorOrResponse instanceof Response) {
// Only retry for server errors
return errorOrResponse.status >= 500;
}
return true;
},
})
.then((res) => res.json())
.then((data) => console.log("Custom retry data:", data))
.catch((err) => console.error("Error with custom retry:", err));
Demonstrate deduplication by firing multiple identical requests simultaneously:
import { fastFetch } from "@hoangsonw/fast-fetch";
const url = "https://pokeapi.co/api/v2/pokemon/ditto";
// Fire two identical requests concurrently.
Promise.all([fastFetch(url), fastFetch(url)])
.then(async ([res1, res2]) => {
const data1 = await res1.json();
const data2 = await res2.json();
console.log("Deduplication demo, data1:", data1);
console.log("Deduplication demo, data2:", data2);
})
.catch((err) => console.error("Deduplication error:", err));
FastFetch comes with a Jest test suite. To run tests:
-
Install dependencies:
npm install
-
Run tests:
npm test
Example test files (found in the __tests__
directory) demonstrate auto-retry, deduplication, and basic fetch functionality.
A demo script is included in the __tests__
directory. To run the demo:
npm run demo
It will execute a series of fetch requests and demonstrate the auto-retry and deduplication features.
Contributions are welcome! Please follow these steps:
- Fork the Repository
- Create a Feature Branch
git checkout -b feature/my-new-feature
- Commit Your Changes
- Submit a Pull Request
For major changes, please open an issue first to discuss your ideas.
This project is licensed under the MIT License.
FastFetch is designed to enhance the native fetch()
experience by adding auto-retry and deduplication features, making your API requests more robust and efficient without caching (use GhostCache for caching). Enjoy building resilient applications!
Happy fetching! 🚀