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

相关推荐
MrSYJ3 分钟前
为什么HttpSecurity会初始化创建两次
java·后端·程序员
专注API从业者4 分钟前
基于 Flink 的淘宝实时数据管道设计:商品详情流式处理与异构存储
大数据·前端·数据库·数据挖掘·flink
龙在天4 分钟前
H5开发,开发照相机,以及组件封装
前端
hinotoyk9 分钟前
TimeUnit源码分享
java
曼妥思11 分钟前
PosterKit:跨框架海报生成工具
前端·开源
binqian31 分钟前
【异步】js中异步的实现方式 async await /Promise / Generator
开发语言·前端·javascript
Jerry说前后端39 分钟前
Android 移动端 UI 设计:前端常用设计原则总结
android·前端·ui
熊猫钓鱼1 小时前
基于Trae CN与TrendsHub快速实现的热点百事通
前端·trae
LIUENG1 小时前
Vue3 响应式原理
前端·vue.js
AAA修煤气灶刘哥1 小时前
Java+AI 驱动的体检报告智能解析:从 PDF 提取到数据落地全指南
java·人工智能·后端