封装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;

相关推荐
弹简特4 分钟前
【JavaEE03-前端部分】JavaScript入门:给网页注入灵魂,从基础到实战玩转交互!
前端·javascript·交互
天人合一peng5 分钟前
unity获得和修改button的text(TMP)
java·前端·unity
jiayong236 分钟前
Vue 3 面试题 - 状态管理与数据流
前端·javascript·vue.js
九皇叔叔10 分钟前
【07】SpringBoot3 MybatisPlus 删除(Mapper)
java·开发语言·mybatis·mybatis plus
sheji341611 分钟前
【开题答辩全过程】以 基于Spring Boot的化妆品销售系统的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端
摇滚侠2 小时前
npm 设置了阿里云镜像,然后全局安装了 pnpm,pnpm 还需要设置阿里云镜像吗
前端·阿里云·npm
程序员清洒8 小时前
Flutter for OpenHarmony:GridView — 网格布局实现
android·前端·学习·flutter·华为
VX:Fegn08958 小时前
计算机毕业设计|基于ssm + vue超市管理系统(源码+数据库+文档)
前端·数据库·vue.js·spring boot·后端·课程设计
0思必得09 小时前
[Web自动化] 反爬虫
前端·爬虫·python·selenium·自动化
徐徐同学9 小时前
cpolar为IT-Tools 解锁公网访问,远程开发再也不卡壳
java·开发语言·分布式