axios 封装,支持取消重复请求
import axios from 'axios';
// axios 实例
const axiosInstance = axios.create({
// 配置 axios 实例
});
// 存放正在进行的请求
const pendingRequests = new Map();
// 取消重复请求
const cancelPendingRequest = (config) => {
const requestKey = getRequestKey(config);
if (pendingRequests.has(requestKey)) {
const cancelToken = pendingRequests.get(requestKey);
cancelToken.cancel('Duplicate request');
pendingRequests.delete(requestKey);
}
};
// 添加请求到 pendingRequests 中
const addPendingRequest = (config) => {
const requestKey = getRequestKey(config);
config.cancelToken = new axios.CancelToken((cancel) => {
if (!pendingRequests.has(requestKey)) {
pendingRequests.set(requestKey, cancel);
}
});
};
// 生成请求 key
const getRequestKey = (config) => {
const { method, url, params, data } = config;
return `${method}_${url}_${JSON.stringify(params)}_${JSON.stringify(data)}`;
};
// 请求拦截器
axiosInstance.interceptors.request.use(
(config) => {
cancelPendingRequest(config);
addPendingRequest(config);
return config;
},
(error) => {
return Promise.reject(error);
}
);
// 响应拦截器
axiosInstance.interceptors.response.use(
(response) => {
const requestKey = getRequestKey(response.config);
pendingRequests.delete(requestKey);
return response;
},
(error) => {
if (axios.isCancel(error)) {
console.log('Request cancelled:', error.message);
return Promise.reject(error);
}
return Promise.reject(error);
}
);
export default axiosInstance;
使用时,直接引入该文件,通过 import axios from ‘路径’ 引入该 axios 实例,就可以使用了。该封装会在请求拦截器中判断当前请求是否与正在进行的请求相同,如果相同则取消之前的请求,并在 pendingRequests 中存放当前请求的 cancel token。在响应拦截器中,会从 pendingRequests 中删除该请求的 cancel token。
如果需要取消正在进行的请求,可以在组件的生命周期中调用 axios.cancel(requestKey) 方法,该方法会根据请求的 key 取消对应的请求。可以使用一个变量来存储当前组件的请求 key,当组件销毁时,取消所有的请求:
import axios from './axios';
export default {
data() {
return {
requestKey: null, // 当前组件的请求 key
};
},
created() {
this.requestData();
},
beforeDestroy() {
axios.cancel(this.requestKey);
},
methods: {
async requestData() {
const { data } = await axios.get('/api/data', { cancelToken: this.$axios.CancelToken });
// 处理请求数据
},
},
};