封装axios请求重试和路由切换时请求取消

请求重试函数:这里注意两个变量__retryCount 和retry分别代表当前次数和重试次数。如果请求中没有配置retry则正常进行不会进行重试。

javascript 复制代码
// 请求重试
async function requestAgainSend(
  err: AxiosError<any, any> & newConfig,
  axios: AxiosInstance,
) {
  const config: AxiosRequestConfig & newConfig = err.config || {};
  if (!config || !config.retry) {
    return Promise.reject(err);
  }
  config.__retryCount = config.__retryCount || 0;
  // 判断是否超过
  if (config.__retryCount >= config.retry) {
    return Promise.reject(err);
  }
  // 重试次数
  config.__retryCount += 1;
  // 延时处理
  const backoff = new Promise(function (resolve) {
    setTimeout(function () {
      resolve("success");
    }, 1000);
  });
  await backoff;
  return await axios(config);
}

请求取消我这里的场景是路由切换时,将上次路由全部取消也可以配置部分取消。注意变量noCancel,他来控制那些不需要被取消。

回顾axios请求取消的几种使用方式:1. 第一种使用AbortController

javascript 复制代码
const controller = new AbortController();

axios.get('/foo/bar', {
   signal: controller.signal
}).then(function(response) {
   //...
});
// 取消请求
controller.abort()

第二种:

javascript 复制代码
const CancelToken = axios.CancelToken;
const source = CancelToken.source();

axios.get('/user/12345', {
  cancelToken: source.token
}).catch(function (thrown) {
  if (axios.isCancel(thrown)) {
    console.log('Request canceled', thrown.message);
  } else {
    // 处理错误
  }
});

axios.post('/user/12345', {
  name: 'new name'
}, {
  cancelToken: source.token
})

// 取消请求(message 参数是可选的)
source.cancel('Operation canceled by the user.');

我是用的是第三种:

javascript 复制代码
const CancelToken = axios.CancelToken;
let cancel;

axios.get('/user/12345', {
  cancelToken: new CancelToken(function executor(c) {
    // executor 函数接收一个 cancel 函数作为参数
    cancel = c;
  })
});

// 取消请求
cancel();

思路:全局维护一个函数集合,其中每一项为cancel(),在请求拦截中添加此函数到集合中,在beforeEach中执行每一个函数并清空集合。

javascript 复制代码
// 在pinia中维护集合和方法,方便调用
import { defineStore } from "pinia";

export const requestStore = defineStore("request", () => {
  const cancelReqList = ref([]);
  const addCancelReq = (cancel: any) => {
    const maxCancelTokenNum = 30; // 最大存cancelToken条数
    if (cancelReqList.value.length >= maxCancelTokenNum) {
      cancelReqList.value.shift();
    }
    cancelReqList.value.push(cancel);
  };
  const removeCancelReq = (index: any) => {
    cancelReqList.value.splice(index, 1);
  };
  return { cancelReqList, addCancelReq, removeCancelReq };
});



// 请求拦截中添加取消函数
service.interceptors.request.use(
  (config: any) => {
    if (!config.noCancel) {
      config.cancelToken = new axios.CancelToken((c) => {
        requestStore().addCancelReq(c);
      });
    }
    
  },
  (err: AxiosError<any, any>) => {
    return Promise.reject(err);
  },
);


// 在router beforeEach路由切换时依次执行。
router.beforeEach(async (to, form, next) => {
  ...
  const { cancelReqList, removeCancelReq } = requestStore();
  cancelReqList.forEach((cancel, index) => {
    cancel();
    removeCancelReq(index);
  });
});

出现的问题

类似这种错误报名你取消请求成功了,但是error的结构不再是以前的结构了

if (error instanceof axios.Cancel) return;

相关推荐
脩衜者9 分钟前
极其灵活且敏捷的WPF组态控件ConPipe 2026
前端·物联网·ui·wpf
掉鱼的猫13 分钟前
灵动如画 —— 初识 Solon Graph Fluent API 编排
java·openai·workflow
Mike_jia14 分钟前
Dockge:轻量开源的 Docker 编排革命,让容器管理回归优雅
前端
周杰伦fans15 分钟前
AndroidStudioJava国内镜像地址gradle
android·java·android-studio
艾莉丝努力练剑15 分钟前
【Linux进程控制(一)】进程创建是呼吸,进程终止是死亡,进程等待是重生:进程控制三部曲
android·java·linux·运维·服务器·人工智能·安全
GISer_Jing20 分钟前
前端GEO优化:AI时代的SEO新战场
前端·人工智能
天天摸鱼的java工程师22 分钟前
RocketMQ 与 Kafka 对比:消息队列选型的核心考量因素
java·后端
没想好d23 分钟前
通用管理后台组件库-4-消息组件开发
前端
uup24 分钟前
SpringBoot 集成 Redis 分布式锁实战:从手动实现到注解式优雅落地
java·redis
文艺理科生25 分钟前
Google A2UI 解读:当 AI 不再只是陪聊,而是开始画界面
前端·vue.js·人工智能