shayloyuki

勇气

 

全局解决取消请求后抛出错误的问题

场景

为了解决该bug(get请求频繁触发获取列表,部分响应时间过长引发响应数据渲染覆盖的问题处理),做过如下处理

取消重复get请求
// request拦截器
service.interceptors.request.use(
  (config) => {
    // 此处省略代码若干

    // get请求频繁触发获取列表,部分响应时间过长引发响应数据渲染覆盖的问题处理(特殊场景下允许同时多次调用,请求头需配置MultipleCalls为true)
    if (config.method === "get" && !config.headers.MultipleCalls) {
      const CancelToken = axios.CancelToken;
      config.cancelToken = new CancelToken(function executor(c) {
        let index = config.url.indexOf("?");
        let url;
        if (index !== -1) {
          url = config.url.slice(0, index);
        } else {
          url = config.url;
        }
        if (getRequestList.has(url)) {
          getRequestList.get(url)();
        }
        getRequestList.set(url, c);
      });
    }
    return config;
  },
  (error) => {
    Promise.reject(error);
  }
);

但是,取消请求后控制台会报如下错误。
image

可以在每个接口中添加 .catch(() => {}) 解决。但这样做太繁琐,因此,需要全局处理。

解决

响应拦截器全局处理取消请求
// 响应拦截器
service.interceptors.response.use(
  (res) => {
    // 此处省略代码若干
  },
  (error) => {
    // if (axios.isCancel(error)) return;
    if (!error) return;
    if (axios.isCancel(error)) {
     // 取消请求时,返回一个空对象或标记,避免进入 catch
      return Promise.resolve({ isCancelled: true });
    }
    if (error.message) {
      const message = error.message;
      if (message == "Network Error") {
        message = "后端接口连接异常";
      } else if (message.includes("timeout")) {
        message = "系统接口请求超时";
      } else if (message.includes("Request failed with status code")) {
        message = "系统接口" + message.substr(message.length - 3) + "异常";
      }
      message.error(message);
    }
    return Promise.reject(error);
  }
);

注意

  • axios.isCancel() 判断是否为取消请求
  • 若仅仅 if (axios.isCancel(error)) return;,不返回结果,会导致被取消的接口,获取的 response 先是 undefined,延迟后才是请求的数据。

参考链接

Promise.resolve()

posted on 2025-06-06 14:35  shayloyuki  阅读(41)  评论(0)    收藏  举报

导航