axios 取消上次重复请求

打印 上一主题 下一主题

主题 2298|帖子 2298|积分 6894

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
在实际开发中,大概会遇到同一个接口被多次调用的情况(比方用户快速点击按钮或页面频繁刷新)。为了制止重复请求浪费资源,可以通过以下计划思路实现取消重复请求。
1.实现思路


  • 唯一标识请求
    为每个请求生成一个唯一标识符(requestKey),通常由请求的 method 和 url 构成。假如必要更准确,可以将 params 或 data 也纳入标识符。
  • 存储请求
    使用一个数据结构(如 Map)来存储当前正在举行的请求及其对应的 AbortController 实例。
  • 取消重复请求
    在发送新请求时,检查 Map 中是否已经存在相同的 requestKey。假如存在,调用 AbortController.abort() 取消上一个请求,并从 Map 中移除。假如不存在,则将当前请求的 AbortController 存入 Map。
  • 移除已完成的请求
    在请求完成或失败时,从 Map 中移除对应的 requestKey。
2.实现步骤


  • 创建 Map 存储请求
    使用 Map 数据结构存储请求的唯一标识符和对应的 AbortController。
  1. const pendingRequests = new Map<string, AbortController>();
复制代码

  • 生成请求的唯一标识符
    定义一个函数,根据请求的 method 和 url 生成唯一标识符。
  1. const getRequestKey = (config: AxiosRequestConfig): string => {
  2.   return `${config.method}:${config.url}`;
  3. };
复制代码

  • 请求拦截器
    在请求拦截器中:检查 Map 中是否存在相同的 requestKey。假如存在,取消上一个请求。
    假如不存在则为当前请求创建一个新的 AbortController,并存入 Map。
  1. axiosInstance.interceptors.request.use((config: AxiosRequestConfig) => {
  2.   const requestKey = getRequestKey(config);
  3.   // 如果存在相同的请求,则取消上一次请求
  4.   if (pendingRequests.has(requestKey)) {
  5.     const controller = pendingRequests.get(requestKey);
  6.     controller?.abort(); // 取消上次请求
  7.     pendingRequests.delete(requestKey); // 从 Map 中移除
  8.   }
  9.   // 为当前请求创建一个新的 AbortController
  10.   const controller = new AbortController();
  11.   config.signal = controller.signal;
  12.   // 将当前请求存储到 Map 中
  13.   pendingRequests.set(requestKey, controller);
  14.   return config;
  15. });
复制代码

  • 响应拦截器
    在响应拦截器中:请求完成后,从 Map 中移除对应的 requestKey。
  1. axiosInstance.interceptors.response.use(
  2.   (response: AxiosResponse) => {
  3.     const requestKey = getRequestKey(response.config);
  4.     pendingRequests.delete(requestKey); // 请求完成后移除
  5.     return response.data;
  6.   },
  7.   (error) => {
  8.     if (axios.isCancel(error)) {
  9.       console.warn("Request canceled:", error.message);
  10.     } else {
  11.       const requestKey = getRequestKey(error.config);
  12.       pendingRequests.delete(requestKey); // 请求完成后移除
  13.       console.error("API Error:", error.response?.data || error.message);
  14.     }
  15.     return Promise.reject(error);
  16.   }
  17. );
复制代码

  • 完备代码实现
  1. import axios, { AxiosRequestConfig, AxiosResponse } from "axios";// 用于存储请求的 Mapconst pendingRequests = new Map<string, AbortController>();
  2. // 生成请求的唯一标识const getRequestKey = (config: AxiosRequestConfig): string => {
  3.   return `${config.method}:${config.url}`;
  4. };
  5. // 创建 Axios 实例const axiosInstance = axios.create({  baseURL: import.meta.env.VITE_BASE_URL, // 替换为你的 API 基础 URL  timeout: 50000, // 请求超时时间  headers: {    "Content-Type": "application/json",  },});// 请求拦截器axiosInstance.interceptors.request.use((config: AxiosRequestConfig) => {
  6.   const requestKey = getRequestKey(config);
  7.   // 如果存在相同的请求,则取消上一次请求
  8.   if (pendingRequests.has(requestKey)) {
  9.     const controller = pendingRequests.get(requestKey);
  10.     controller?.abort(); // 取消上次请求
  11.     pendingRequests.delete(requestKey); // 从 Map 中移除
  12.   }
  13.   // 为当前请求创建一个新的 AbortController
  14.   const controller = new AbortController();
  15.   config.signal = controller.signal;
  16.   // 将当前请求存储到 Map 中
  17.   pendingRequests.set(requestKey, controller);
  18.   return config;
  19. });
  20. // 响应拦截器axiosInstance.interceptors.response.use(
  21.   (response: AxiosResponse) => {
  22.     const requestKey = getRequestKey(response.config);
  23.     pendingRequests.delete(requestKey); // 请求完成后移除
  24.     return response.data;
  25.   },
  26.   (error) => {
  27.     if (axios.isCancel(error)) {
  28.       console.warn("Request canceled:", error.message);
  29.     } else {
  30.       const requestKey = getRequestKey(error.config);
  31.       pendingRequests.delete(requestKey); // 请求完成后移除
  32.       console.error("API Error:", error.response?.data || error.message);
  33.     }
  34.     return Promise.reject(error);
  35.   }
  36. );
  37. export default axiosInstance;
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

立聪堂德州十三局店

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表