axios取消请求

111 阅读2分钟

最近项目里面有一个需求,就是选择器每次选择都会触发后端接口请求数据,但是用户会频繁切换选择项,导致多个相同请求触发,影响页面的流畅,所以我要把多个重复请求取消掉只留下最后一次接口请求拿到数据。

由于项目调用接口采用的是axios,我就百度搜索了一下axios如何取消请求。经过搜索发现,我的项目axios版本较低,axios版本在0.22.0之下的话,axios采用的是CancenToken方法来取消接口请求。

在经过一番cv和调试,发现简书上给的方法并不完全正确,自测就可以发现并不满足重复请求时只保留最后一次,经过研究得出结论,还是唯一标识的问题,然后就开始优化代码,最终解决了问题。

以下是vue项目request.js封装取消请求的代码:

const getUrlKey = (config) => {
  return `${config.method}:${config.url}`;
};

// 修改取消令牌的管理方式
const pendingRequests = new Map();

// 优化取消请求的函数
const cancelRequest = (config) => {
  const requestKey = getUrlKey(config);
  if (pendingRequests.has(requestKey)) {
    // 如果存在相同请求,则取消之前的请求
    const cancelToken = pendingRequests.get(requestKey);
    cancelToken.cancel(`重复请求被取消: ${requestKey}`);
    pendingRequests.delete(requestKey);
  }
  // 为当前请求创建新的取消令牌
  const source = axios.CancelToken.source();
  config.cancelToken = source.token;
  pendingRequests.set(requestKey, source);
};

// 清理已完成的请求
const removePendingRequest = (config) => {
  const requestKey = getUrlKey(config);
  if (pendingRequests.has(requestKey)) {
    pendingRequests.delete(requestKey);
  }
};

// 不允许多次重复调用的API黑名单
const blackList = ["/api/chg/change/existAppAlter/getCmsAppChangeInfo"];

// 修改请求拦截器
service.interceptors.request.use(
  (config) => {
    const token = util.cookies.get("token");
    config.headers["Authorization"] = token;
    
    // 直接调用 cancelRequest,内部会判断是否需要处理
    cancelRequest(config);
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);
service.interceptors.response.use(
  (response) => {
    // 请求完成后,清理掉已完成的请求
    removePendingRequest(response.config);
    ...
  },
  (error) => {
    // 如果是取消请求的错误,直接返回,不需要错误提示
    if (axios.isCancel(error)) {
      console.log("Request canceled:", error.message);
      return Promise.reject(error);
    }
    // 请求出错也要清理掉
    error.config && removePendingRequest(error.config);
    errorLog(error);
    return Promise.reject(error);
  }
);

你的问题解决的话请给个赞支持一下,不然没有为爱发电的动力了。