用于记录
开发中经常会遇到请求重复的问题,当需要的资源一样的情况下,多次请求会造成服务器不必要的工作,为了更好的性能,需要取消请求的操作在axios的请求拦截器中给当前请求添加controller,每个请求的controller唯一,所以需要在拦截器中定义
instance.interceptors.request.use(async function (config) {
const controller = new AbortController();
const signal = controller.signal;
config.signal = signal;
config.controller = controller;
//删除之前url的请求
await deletePending(config);
// 将当前请求添加到 pending 中
await addPending(config);
return config;
});
响应之后同样也该删除
instance.interceptors.response.use(
function (response) {
deletePending(response.config);
return response.data;
},
function (error) {
if (error.code !== "ERR_CANCELED") {
return Promise.reject(error);
}
}
);
定义deletePending和addPending方法,需要定义一个全局的map对象,用于关联请求和取消方法。
const pending = new Map();
export const addPending = (config) => {
const newParams = { ...config.params };
const newData = { ...config.data };
const url = [
config.url,
JSON.stringify(newData),
JSON.stringify(newParams),
config.method,
].join("&");
pending.set(url, config.controller);
};
export const deletePending = (config) => {
const newParams = { ...config.params };
const newData = { ...config.data };
const url = [
config.url,
JSON.stringify(newData),
JSON.stringify(newParams),
config.method,
].join("&");
if (pending.get(url)) {
// 取消请求
const cancel = pending.get(url);
cancel.abort();
pending.delete(url);
}
};
另一个版本
// --------------------------
// 文件: request.js
// --------------------------
import axios from 'axios';
// 存储所有进行中的请求控制器 { key: AbortController }
const pendingRequests = new Map();
/**
* 生成请求的唯一标识键
* (可根据项目需求调整序列化规则)
*/
function generateReqKey(config) {
const { method, url, params, data } = config;
return [method, url, JSON.stringify(params), JSON.stringify(data)].join('&');
}
/**
* 添加请求到等待列表
*/
function addPendingRequest(config) {
const key = generateReqKey(config);
if (!pendingRequests.has(key)) {
const controller = new AbortController();
config.signal = controller.signal; // 挂载到请求配置
pendingRequests.set(key, controller);
} else {
// 已存在相同请求,直接复用之前的 signal
config.signal = pendingRequests.get(key).signal;
}
}
/**
* 移除已完成/已取消的请求
*/
function removePendingRequest(config) {
const key = generateReqKey(config);
if (pendingRequests.has(key)) {
pendingRequests.delete(key);
}
}
/**
* 取消所有进行中的请求
*/
export function cancelAllRequests() {
pendingRequests.forEach(controller => controller.abort());
pendingRequests.clear();
}
/**
* 取消指定请求
*/
export function cancelRequest(config) {
const key = generateReqKey(config);
if (pendingRequests.has(key)) {
pendingRequests.get(key).abort();
pendingRequests.delete(key);
}
}
// 创建 Axios 实例
const instance = axios.create({
timeout: 15000,
// 其他全局配置...
});
// 请求拦截器 - 自动添加取消控制器
instance.interceptors.request.use(config => {
// 自动取消重复请求 (需关闭则删除此行)
cancelRequest(config);
addPendingRequest(config);
return config;
}, error => {
return Promise.reject(error);
});
// 响应拦截器 - 自动清理已完成请求
instance.interceptors.response.use(response => {
removePendingRequest(response.config);
return response;
}, error => {
// 统一处理取消请求的错误
removePendingRequest(error.config || {});
if (axios.isCancel(error)) {
return Promise.reject({ isCanceled: true }); // 自定义取消标识
}
// 其他错误处理...
return Promise.reject(error);
});
export default instance;