Composable Axios adapter enhancers for cache, throttle, and retry.
Quick Start • API • Migration • npm
axios-extensions gives you production-friendly request behavior without replacing Axios itself.
This README targets v4.x. Looking for older docs? See v3.1.7.
Migrating from v3? Read MIGRATION.md.
| Enhancer | What it does | Typical use case |
|---|---|---|
cacheAdapterEnhancer | Request-level response caching | Avoid duplicate reads for the same resource |
throttleAdapterEnhancer | Dedupe/throttle GET requests inside a time window | Prevent burst requests during rapid UI interactions |
retryAdapterEnhancer | Retry failed requests with global/per-request overrides | Improve resilience on flaky networks |
These enhancers are designed to be composed together on top of Axios adapters.
| If you want to... | Use |
|---|---|
| Avoid duplicate reads and reuse response results | cacheAdapterEnhancer |
| Collapse repeated GET requests in rapid bursts | throttleAdapterEnhancer |
| Survive transient network/backend failures | retryAdapterEnhancer |
| Package | Supported version |
|---|---|
| Node.js | >= 18 |
| axios | >= 1.0.0 |
axios v0.19.0 is not supported due to an Axios custom config issue: https://github.com/axios/axios/pull/2207
npm i axios-extensions
yarn add axios-extensions
Browser UMD build:
<!-- exposed as window['axios-extensions'] -->
<script src="https://unpkg.com/axios-extensions/dist/axios-extensions.min.js"></script>
Compose all three enhancers in one adapter:
import axios from 'axios';
import {
cacheAdapterEnhancer,
throttleAdapterEnhancer,
retryAdapterEnhancer,
} from 'axios-extensions';
const adapter = retryAdapterEnhancer(
throttleAdapterEnhancer(
cacheAdapterEnhancer(axios.defaults.adapter!),
{ threshold: 1000 },
),
{ times: 2 },
);
export const http = axios.create({
baseURL: '/api',
adapter,
});
Per-request overrides:
await http.get('/users', {
forceUpdate: true,
threshold: 3000,
retryTimes: 3,
});
Common composition presets:
// 1) Cache only
const cacheOnly = cacheAdapterEnhancer(axios.defaults.adapter!);
// 2) Cache + throttle (great for list/search pages)
const cacheAndThrottle = throttleAdapterEnhancer(
cacheAdapterEnhancer(axios.defaults.adapter!),
{ threshold: 1000 },
);
// 3) Full resilience pipeline
const resilient = retryAdapterEnhancer(cacheAndThrottle, { times: 2 });
cacheAdapterEnhancerWhen to use: cache requests (GET by default) and optionally customize cache strategy/key generation.
cacheAdapterEnhancer(adapter: NonNullable<AxiosRequestConfig['adapter']>, options?: {
cacheable?: (config: AxiosRequestConfig) => boolean | ICacheLike<any>;
keyGenerator?: (config: AxiosRequestConfig) => string;
defaultCache?: ICacheLike<AxiosPromise>;
}): AxiosAdapter
Default behavior:
config.cache is set, it is used as overridenew Cache({ ttl: 5 * 60 * 1000, max: 100 })Common request options (module-augmented on AxiosRequestConfig):
cache?: boolean | ICacheLike<any>forceUpdate?: booleanExample: enable cache for GET by default, but force refresh per request:
await http.get('/users', { forceUpdate: true });
Example: opt-in cache only:
const adapter = cacheAdapterEnhancer(axios.defaults.adapter!, {
cacheable: config => config.cache ?? false,
});
Example: cache GET + POST with a URL-only key (safe only when params/body do not affect response):
const adapter = cacheAdapterEnhancer(axios.defaults.adapter!, {
cacheable: config => config.method === 'get' || config.method === 'post',
keyGenerator: config => `${config.method}:${config.url}`,
});
config.url alone is only safe when query params/body do not change response semantics. Otherwise include params and (for non-GET) data in the key.
throttleAdapterEnhancerWhen to use: dedupe GET requests triggered repeatedly within a short interval.
throttleAdapterEnhancer(adapter: NonNullable<AxiosRequestConfig['adapter']>, options?: {
threshold?: number;
cache?: ICacheLike<{ timestamp: number; value?: AxiosPromise }>;
}): AxiosAdapter
Default behavior:
threshold (default 1000ms) reuse in-flight/previous promiseRequest-level override:
threshold?: number on AxiosRequestConfigawait http.get('/users', { threshold: 3000 });
retryAdapterEnhancerWhen to use: retry transient failures without rewriting request logic.
retryAdapterEnhancer(adapter: AxiosAdapter, options?: {
times?: number;
}): AxiosAdapter
Default behavior:
times (default 2)retryTimes?: numberawait http.get('/critical-endpoint', { retryTimes: 3 });
axios-extensions augments Axios request types for:
cacheforceUpdatethresholdretryTimesWhen importing shared cache contracts in TypeScript, use type-only imports:
import type { ICacheLike } from 'axios-extensions';
If your project has strict interop settings, enabling these can improve import ergonomics:
esModuleInterop: trueallowSyntheticDefaultImports: trueSet process.env.LOGGER_LEVEL=info in Node-based development to enable internal info logging.
npm run lint
npm test
npm run build
MIT