axios 取消上次重复请求
在实际开发中,大概会遇到同一个接口被多次调用的情况(比方用户快速点击按钮或页面频繁刷新)。为了制止重复请求浪费资源,可以通过以下计划思路实现取消重复请求。1.实现思路
[*] 唯一标识请求
为每个请求生成一个唯一标识符(requestKey),通常由请求的 method 和 url 构成。假如必要更准确,可以将 params 或 data 也纳入标识符。
[*] 存储请求
使用一个数据结构(如 Map)来存储当前正在举行的请求及其对应的 AbortController 实例。
[*] 取消重复请求
在发送新请求时,检查 Map 中是否已经存在相同的 requestKey。假如存在,调用 AbortController.abort() 取消上一个请求,并从 Map 中移除。假如不存在,则将当前请求的 AbortController 存入 Map。
[*] 移除已完成的请求
在请求完成或失败时,从 Map 中移除对应的 requestKey。
2.实现步骤
[*]创建 Map 存储请求
使用 Map 数据结构存储请求的唯一标识符和对应的 AbortController。
const pendingRequests = new Map<string, AbortController>();
[*]生成请求的唯一标识符
定义一个函数,根据请求的 method 和 url 生成唯一标识符。
const getRequestKey = (config: AxiosRequestConfig): string => {
return `${config.method}:${config.url}`;
};
[*]请求拦截器
在请求拦截器中:检查 Map 中是否存在相同的 requestKey。假如存在,取消上一个请求。
假如不存在则为当前请求创建一个新的 AbortController,并存入 Map。
axiosInstance.interceptors.request.use((config: AxiosRequestConfig) => {
const requestKey = getRequestKey(config);
// 如果存在相同的请求,则取消上一次请求
if (pendingRequests.has(requestKey)) {
const controller = pendingRequests.get(requestKey);
controller?.abort(); // 取消上次请求
pendingRequests.delete(requestKey); // 从 Map 中移除
}
// 为当前请求创建一个新的 AbortController
const controller = new AbortController();
config.signal = controller.signal;
// 将当前请求存储到 Map 中
pendingRequests.set(requestKey, controller);
return config;
});
[*]响应拦截器
在响应拦截器中:请求完成后,从 Map 中移除对应的 requestKey。
axiosInstance.interceptors.response.use(
(response: AxiosResponse) => {
const requestKey = getRequestKey(response.config);
pendingRequests.delete(requestKey); // 请求完成后移除
return response.data;
},
(error) => {
if (axios.isCancel(error)) {
console.warn("Request canceled:", error.message);
} else {
const requestKey = getRequestKey(error.config);
pendingRequests.delete(requestKey); // 请求完成后移除
console.error("API Error:", error.response?.data || error.message);
}
return Promise.reject(error);
}
);
[*]完备代码实现
import axios, { AxiosRequestConfig, AxiosResponse } from "axios";// 用于存储请求的 Mapconst pendingRequests = new Map<string, AbortController>();
// 生成请求的唯一标识const getRequestKey = (config: AxiosRequestConfig): string => {
return `${config.method}:${config.url}`;
};
// 创建 Axios 实例const axiosInstance = axios.create({baseURL: import.meta.env.VITE_BASE_URL, // 替换为你的 API 基础 URLtimeout: 50000, // 请求超时时间headers: { "Content-Type": "application/json",},});// 请求拦截器axiosInstance.interceptors.request.use((config: AxiosRequestConfig) => {
const requestKey = getRequestKey(config);
// 如果存在相同的请求,则取消上一次请求
if (pendingRequests.has(requestKey)) {
const controller = pendingRequests.get(requestKey);
controller?.abort(); // 取消上次请求
pendingRequests.delete(requestKey); // 从 Map 中移除
}
// 为当前请求创建一个新的 AbortController
const controller = new AbortController();
config.signal = controller.signal;
// 将当前请求存储到 Map 中
pendingRequests.set(requestKey, controller);
return config;
});
// 响应拦截器axiosInstance.interceptors.response.use(
(response: AxiosResponse) => {
const requestKey = getRequestKey(response.config);
pendingRequests.delete(requestKey); // 请求完成后移除
return response.data;
},
(error) => {
if (axios.isCancel(error)) {
console.warn("Request canceled:", error.message);
} else {
const requestKey = getRequestKey(error.config);
pendingRequests.delete(requestKey); // 请求完成后移除
console.error("API Error:", error.response?.data || error.message);
}
return Promise.reject(error);
}
);
export default axiosInstance;
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]