axios实现,在一个极短时间内,请求同一个接口,若传参完全一样,则使用浏览器中的缓存中的上次的值。同时,上次的值应该在指定时间内可以自动清除。请写一个axios适配器。实现上述功能
axios实现,在一个极短时间内,请求同一个接口,若传参完全一样,则使用浏览器中的缓存中的上次的值。同时,上次的值应该在指定时间内可以自动清除。请写一个axios适配器。实现上述功能。
在axios中,我们可以利用浏览器的缓存机制(HTTP缓存)来实现这个需求。不过,浏览器的HTTP缓存主要依赖于服务器返回的Cache-Control等响应头信息,并不能完全按照指定时间自动清除。
但如果你想要在客户端实现一个简易版本的缓存适配器,可以使用内存缓存(如Map或对象)存储请求结果,并设置一个过期时间。
我们将适配器抽离出来作为一个单独的模块,并且通过axios实例配置的方式引入。以下是一个将缓存适配器独立封装的例子:
首先创建一个axiosCacheAdapter.js文件:
import axios from 'axios';
const cache = new Map();
const EXPIRATION_TIME_MS = 60 * 1000; // 缓存过期时间(例如:1分钟)
const cacheAdapterEnhancer = config => {
const { url, method, params, data } = config;
const cacheKey = JSON.stringify({ url, method, params, data });
if (cache.has(cacheKey)) {
const cachedResult = cache.get(cacheKey);
if (Date.now() - cachedResult.timestamp < EXPIRATION_TIME_MS) {
return Promise.resolve(cachedResult.data);
} else {
cache.delete(cacheKey);
}
}
return axios.defaults.adapter(config).then((response) => {
const cacheValue = {
timestamp: Date.now(),
data: response.data,
};
cache.set(cacheKey, cacheValue);
return response;
});
};
export default cacheAdapterEnhancer;
然后在主应用中引入并使用这个适配器:
import axios from 'axios';
import cacheAdapterEnhancer from './axiosCacheAdapter';
// 创建axios实例并配置缓存适配器
const instance = axios.create({
adapter: cacheAdapterEnhancer,
});
// 使用自定义的axios实例发送请求
instance.get('/your-api-endpoint', { params: yourParams })
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error(error);
});
这样就实现了适配器的解耦和复用,可以根据需要在不同的地方引入并配置给不同的axios实例。
在这种场景下为何使用的是叫适配器,为啥使用这种设计模式?
在这种场景下,我们虽然没有明确提到“适配器”这个词,但实际设计的机制确实体现了一种适配器模式的应用。
适配器模式(Adapter Pattern)是一种结构型设计模式,它允许将一个接口转换为客户希望的另一个接口,从而使原本不兼容的类可以协同工作。
在上述axios缓存适配器的例子中:
- 原始接口:这里的原始接口是axios提供的HTTP请求功能,它会直接与服务器进行交互以获取数据。
- 目标接口:目标接口是我们期望的行为,即当短时间内重复请求相同接口且参数相同时,从本地缓存而不是服务器获取数据。
- 适配器:创建的
cacheAdapterEnhancer
就是一个适配器,它接收axios原有的请求配置,并通过自定义逻辑来决定是否从缓存中返回数据还是发起实际网络请求。这个适配器将axios原始的接口行为适配成了包含缓存功能的新接口。
通过这种方式,我们无需修改axios库本身的代码,而是通过封装一个适配器,在不改变原有接口的基础上,为axios添加了新的缓存处理逻辑,从而实现了新旧系统之间的解耦和复用,这正是适配器模式的核心思想。
对于缓存的处理来说,使用拦截器还是适配器更合适?给出你的理由
对于缓存的处理,使用拦截器(Interceptor)通常更为合适。理由如下:
-
职责分离:
- 请求拦截器(Request Interceptor)可以用于在发送请求前检查是否有可用的缓存,并决定是否从缓存中获取数据或继续发起网络请求。
- 响应拦截器(Response Interceptor)则可以在接收到服务器响应后,将数据存入缓存。
-
复用性与灵活性:
- 拦截器是基于整个axios实例进行配置的,这意味着你可以在全局范围内设置缓存策略,也可以为特定的axios实例设置不同的缓存逻辑。
- 当需要调整缓存策略时,只需修改拦截器逻辑即可,而无需改动其他业务代码。
-
生命周期控制:
- 拦截器在整个请求-响应周期中有明确的位置,能方便地在请求前后执行相应的操作,如在请求前检查缓存,在响应后更新缓存等。
-
适配器功能定位:
- 适配器(Adapter)更适合于替换底层网络请求库,例如如果你要将axios的xhr实现换成fetch或其他自定义的HTTP客户端,这时适配器更符合其设计意图。
总结来说,由于缓存处理是在请求和响应阶段完成的,并且与具体的网络通信实现无关,因此采用拦截器模式更加合理和便捷。而适配器模式更多用于改变接口以适应不同环境或者组件之间的交互,与缓存管理的核心需求并不十分契合。