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

相关推荐
和你一起去月球几秒前
TypeScript - 函数(下)
javascript·git·typescript
_Legend_King6 分钟前
vue3 + elementPlus 日期时间选择器禁用未来及过去时间
javascript·vue.js·elementui
爱吃青椒不爱吃西红柿‍️7 分钟前
华为ASP与CSP是什么?
服务器·前端·数据库
余生H8 分钟前
transformer.js(三):底层架构及性能优化指南
javascript·深度学习·架构·transformer
一棵开花的树,枝芽无限靠近你11 分钟前
【PPTist】添加PPT模版
前端·学习·编辑器·html
陈王卜13 分钟前
django+boostrap实现发布博客权限控制
java·前端·django
小码的头发丝、14 分钟前
Spring Boot 注解
java·spring boot
java亮小白199719 分钟前
Spring循环依赖如何解决的?
java·后端·spring
景天科技苑21 分钟前
【vue3+vite】新一代vue脚手架工具vite,助力前端开发更快捷更高效
前端·javascript·vue.js·vite·vue项目·脚手架工具
SameX23 分钟前
HarmonyOS Next 安全生态构建与展望
前端·harmonyos