longmo-plugin-axios
v2.0.0
Published
axios插件,`axios-cache-interceptor`
Maintainers
Readme
longmo-plugin-axios
axios插件,axios-cache-interceptor
支持到 1.1.x 需要同步安装下方配置
pnpm add localforage@^1.10.0 lru-cache@^11.2.4快速使用
使用 setup返回一个平台的axios最佳实践配置,并提供钩子函数进行自定义,具体见下面说明
import {setup} from 'longmo-plugin-axios'
const _axios = setup({}) // 返回axios实例,用法见axios的文档
export default _axiossetup
配置了接口的通用错误处理能力
返回axios实例,使用默认配置可快速使用,简化配置,不和任何框架绑定,适用所有平台的UI框架
在hussar平台可快速使用, 注意重复setup都会返回一个新的axios实例,可全局注册复用实例
如果setup不能满足项目需求,可自行使用axios配置,配置说明见上。
基础使用
import {setup} from 'longmo-plugin-axios'
const _axios = setup()
export default _axios高级使用
loading.js全局loading配置
import {Loading} from 'element-ui'
export default {
instance: null,
show() {
this.instance = Loading.service({fullscreen: true, lock: true, background: 'rgba(255, 255, 255, 0.2)'})
},
hide() {
if (this.instance) {
this.instance.close()
}
}
}plugins/axios.js配置
import loading from './loading.js'
import {Notification} from 'element-ui'
import {setup} from 'longmo-plugin-axios'
const _axios = setup({
cache: {enable: true, ttl: 3 * 60 * 1000}, // 见上
loading: loading,
errorAction: (error) => {
Notification.error({
title: error.name, // 如果不想使用默认标题,可通过error.type判断设置
message: error.message
})
},
authFailAction: () => {
// logout 返回到登录页面逻辑
}
})
export default _axios- 请求使用参数
import axios from './plugins/axios.js'
axios.get('/user')
axios.get('/list', {
manual: true, // 手动处理报文,不用默认方式处理
loading: true, // 请求时,有网络请求loading, 前提是在setup设置了loading
})
setupOptions
// setup 配置参数
export type setupConfig = {
cache?: CacheOptions, // 见 cacheAdapterEnhancer 配置
loading?: IAxiosLoading, // 见 IAxiosLoading 默认不显示网络请求全局loading,需要在每个请求设置
authFailAction?(): void, // 认证失败调用的函数,可在这里处理跳转逻辑
errorAction?(error: IError): void // 网络请求失败错误处理逻辑
}
// 网络请求 全局loading,和UI框架解耦
export interface IAxiosLoading {
instance: any;
show(): void;
hide(): void;
}
// 网络请求错误类型
export enum IErrorType {
NETWORK = 'NETWORK', // 网络异常 404 500
SYSTEM = 'SYSTEM' // 系统异常 response.status=200, 系统报错
}
// 异常接口
export interface IError extends Error {
name: string; // 网络异常 系统异常
message: string; // 错误信息
type: IErrorType; // 异常类型
code: string | number // 错误码,网络异常错误码 系统异常错误码
}use(可选)
使用插件挂载全局
vue2:挂载Vue.prototype上import Vue form 'vue' import {setup, use} from 'longmo-plugin-axios' use(setup(), Vue)vue3:挂载app.config.globalPropertiesimport {createApp} from 'vue' import App from './App.vue' import {setup, use} from 'longmo-plugin-axios' const app = createApp(App) use(setup({}), app) app.mount('#app')使用挂载全局
$axios实例{ mounted () { this.$axios.get('/user') } }
cacheAdapterEnhancer
用于axios的缓存适配器,将存储请求结果存储在可配置的存储中,以防止不必要的网络请求。
缓存store使用的localforage
const forageStore = localforage.createInstance({
driver: [localforage.INDEXEDDB, localforage.LOCALSTORAGE],
name: 'longmo-axios-cache-db',
storeName: 'longmo_axios_cache_table',
});
const forageStorage: BuildStorage = {
async set(key: string, value) {
await forageStore.setItem(key, value);
},
async find(key: string) {
return (await forageStore.getItem(key)) ?? undefined;
},
async remove(key: string) {
return await forageStore.removeItem(key);
},
async clear() {
return await forageStore.clear();
},
缓存策略,不支持的浏览器降级处理逻辑,优先级顺序: IndexedDB > WebSQL> localStorage
基础使用
接口缓存适配器
import axios from 'axios'
import {setup, buildStorage, forageStorage} from 'longmo-plugin-axios'
const cacheOptions = {
enabled: true,
ttl: 5 * 60 * 1000,// 设置缓存有效期毫秒值
storage: buildStorage(forageStorage),
}
const axiosOptions = {
baseURL: '',
timeout: 60 * 1000,
'Content-Type': 'application/json;charset=UTF-8',
}
const axios = setup({
...axiosOptions,
cache: cacheOptions
})
axios.get('https://httpbin.org/get'); // 发起真实网络请求
axios.get('https://httpbin.org/get'); // 使用前一个请求的缓存中的响应结果,而不发出实际的http请求覆盖实例的配置参数
在使用特定的缓存配置设置了axios-cache-adapter”`之后,您可以在单个请求中覆盖该配置的
对时效性要求比较高的接口,可以在请求中禁用cache,设置ignoreCache=true,其他配置看下面参数说明
import axios from 'axios'
import {setup, buildWebStorage} from 'longmo-plugin-axios'
const axios = setup({
cache: {
enabled: true,
ttl: 5 * 60 * 1000,// 设置缓存有效期毫秒值
storage: buildWebStorage(localStorage, 'prefix-key'),
}
})
// 设置该请求的缓存有效时间毫秒数
axios.get('https://httpbin.org/get', {
cache: {
ttl: 2 * 60 * 1000
}
});
// 手动禁用缓存,并调用真实的http请求
axios.get('https://httpbin.org/get', {
cache: {
enable: false,
}
});cacheOptions
更多高级设置参数,请查看axios-cache-interceptor
{
/**
* A storage interface is the entity responsible for saving, retrieving and serializing
* data received from network and requested when a axios call is made.
*
* See the [Storages](https://axios-cache-interceptor.js.org/guide/storages) page for
* more information.
*
* @default buildMemoryStorage
* @see https://axios-cache-interceptor.js.org/config#storage
*/
storage: AxiosStorage;
/**
* The function used to create different keys for each request. Defaults to a function
* that priorizes the id, and if not specified, a string is generated using the
* `method`, `baseURL`, `params`, `data` and `url`.
*
* You can learn on how to use them on the [Request
* ID](https://axios-cache-interceptor.js.org/guide/request-id#custom-generator) page.
*
* @default defaultKeyGenerator
* @see https://axios-cache-interceptor.js.org/config#generatekey
*/
generateKey: KeyGenerator;
/**
* The function used to interpret all headers from a request and determine a time to
* live (`ttl`) number.
*
* **Many REST backends returns some variation of `Cache-Control: no-cache` or
* `Cache-Control: no-store` headers, which tell us to ignore caching at all. You shall
* disable `headerInterpreter` for those requests.**
*
* **If the debug mode prints `Cache header interpreted as 'dont cache'` this is
* probably the reason.**
*
* The possible returns are:
*
* - `'dont cache'`: the request will not be cached.
* - `'not enough headers'`: the request will find other ways to determine the TTL value.
* - `number`: used as the TTL value.
*
* @default defaultHeaderInterpreter
* @see https://axios-cache-interceptor.js.org/config#headerinterpreter
*/
headerInterpreter: HeaderInterpreter;
/**
* The function that will be used to intercept the request before it is sent to the
* axios adapter.
*
* It is the main function of this library, as it is the bridge between the axios
* request and the cache.
*
* _It wasn't meant to be changed, but if you need to, you can do it by passing a new
* function to this property._*
*
* See its code for more information
* [here](https://github.com/arthurfiorette/axios-cache-interceptor/tree/main/src/interceptors).
*
* @default defaultRequestInterceptor
* @see https://axios-cache-interceptor.js.org/config#requestinterceptor
*/
requestInterceptor: AxiosInterceptor<InternalCacheRequestConfig<unknown, unknown>>;
/**
* The function that will be used to intercept the request after it is returned by the
* axios adapter.
*
* It is the second most important function of this library, as it is the bridge between
* the axios response and the cache.
*
* _It wasn't meant to be changed, but if you need to, you can do it by passing a new
* function to this property._*
*
* See its code for more information
* [here](https://github.com/arthurfiorette/axios-cache-interceptor/tree/main/src/interceptors).
*
* @default defaultResponseInterceptor
* @see https://axios-cache-interceptor.js.org/config#responseinterceptor
*/
responseInterceptor: AxiosInterceptor<
Partial<CacheAxiosResponse<unknown, unknown>> & AxiosResponse<unknown, unknown>
>;
}devtool

注意
Axios拦截器对请求和响应的运行方式不同
请求拦截器按相反顺序执行——最后添加的拦截器最先运行(LIFO——后进先出)。
响应拦截器按正常顺序执行——第一个添加的拦截器首先运行(FIFO -先进先出)
// This will run BEFORE the cache interceptor
axios.interceptors.request.use((req) => req);
// This will run AFTER the cache interceptor
axios.interceptors.response.use((res) => res);
setupCache(axios);
// This will run AFTER the cache interceptor
axios.interceptors.request.use((req) => req);
// This will run BEFORE the cache interceptor
axios.interceptors.response.use((res) => res);扩展类型
使用 longmo-plugin-axios 时,你会注意到它的类型与默认的 AxiosInstance、AxiosRequestConfig 和 AxiosResponse 不同。
这是因为选择覆盖 Axios 的接口,而不是扩展,以避免与其他库的变更造成破坏。
然而,这也意味着在与其他包集成或创建自定义拦截器时,你需要覆盖/扩展我们自己的类型,
如CacheInstance、CacheRequestConfig和CacheAxiosResponse,以符合你的需求。
具体步骤如下:
declare module 'longmo-plugin-axios' {
interface TCAxiosRequestConfig<R = unknown, D = unknown> {
customProperty: string;
}
}流与非 JSON
这个库无法处理流或缓冲区,所以如果你仍然需要 response.data 作为流或缓冲区,就需要手动缓存。
如果你能将响应数据收集成可序列化格式,axios-cache-interceptor 可以通过 transformResponse 选项帮你处理。
你可以使用 Axios 的原生 transformResponse 选项,这是一个接收响应并返回字符串或缓冲区的函数。
Axios Cache Interceptor 只能处理可序列化的数据类型,所以你需要将响应转换为字符串或缓冲区。
import Axios from 'axios';
import {setupCache} from 'axios-cache-interceptor';
const instance = Axios.create();
const axios = setupCache(instance);
const response = await axios.get('my-url-that-returns-a-stream', {
responseType: 'stream',
transformResponse(response) {
// You will need to implement this function.
return convertStreamToStringOrObject(response.data);
}
});
response.data; // Will be a string and will be able to be cached.清除所有缓存
axios.storage.clear();
await axios.storage.remove(fetchedResponse.id);自定义key
buildKeyGenerator 方法入参为 axiosConfig,
出参若是对象,则使用hash进行转换,若是字符串或者数字,统一转为字符串,作为key
import {buildKeyGenerator, buildStorage, buildURLWithAxiosConfig, forageStorage, setup} from 'longmo-plugin-axios'
const _axios = setup({
cache: {
enabled: true,
debug: console.error,
generateKey: buildKeyGenerator((request) =>
buildURLWithAxiosConfig(request)
),
storage: buildStorage(forageStorage),
ttl: 1000 * 2, // 过期时间 2s
},
});
export default _axios;ttl 是 Time To Live(生存时间) 的缩写,它决定了 缓存条目在内存中可以保留多久(单位:毫秒)
| 配置项 | 作用 |
|-------------------------|------------------------------------------------------------------|
| ttl: 99999 | 默认缓存有效期为 99,999 毫秒(约 100 秒) |
| interpretHeader: true | 优先从 HTTP 响应头(如 Cache-Control、Age)中解析真实的缓存时间,而不是直接用 ttl |
🧠 interpretHeader: true 时的逻辑(重点!)
当 interpretHeader 为 true(默认值),ttl 只是“兜底值”,实际 TTL 会根据服务器返回的 HTTP 缓存头动态计算:
- 服务器返回:
Cache-Control: max-age=300 Age: 50 - 那么实际缓存时间 =
max-age - Age = 300 - 50 = 250 秒 - 这个 250 秒会覆盖你设置的
ttl: 99999 - 所以你在日志中看到:
log(`Cache TTL info: ${cacheInformation.ttl}`); // 输出的是 250000(毫秒),不是 99999!
📌 总结:ttl 的作用
| 场景 | ttl 的作用 |
|-----------------------------|--------------------------------------|
| interpretHeader: true(默认) | 备用值:当服务器没返回有效缓存头时才用 |
| interpretHeader: false | 强制使用:所有请求都按这个时间缓存 |
| 单位 | 毫秒(ms) |
| 默认值 | 如果不传 ttl,默认是 1000 * 60 * 5(5 分钟) |
todo
- [x] 默认关闭适配器
- [ ] 添加重试适配器
- [x] 抽离默认拦截器适配器
- [x] 升级 lru-cache 版本
- [x] 支持清除所有缓存方法(例如退出登录时需要清除所有缓存)
- [x] 支持检查响应是否是来自缓存
- [x] 支持强制更新某个接口的缓存
- [x] 添加缓存key自定义生成规则配置项
- 支持get请求时添加缓存,put、patch、delete 请求时,使相同url的缓存失效
