尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

vue3+ts 简单封装axios:实现错误重试、重复请求取消、手动取消

vue3+ts 简单封装axios:实现错误重试、重复请求取消、手动取消
📅 发布时间:2026/6/20 21:31:01

注意:需要安装crypto-js库

  1. 在utils\request.ts中:

    import axios from "axios";
    import type { InternalAxiosRequestConfig, AxiosResponse, AxiosInstance } from "axios";
    import { useRequeryStore } from "@/store/request";
    const useRequeryStoreInfo = useRequeryStore();let isLogoutShowing = false; // 登录过期弹窗锁// 创建Axios实例
    const axiosInstance: AxiosInstance = axios.create({baseURL: import.meta.env.VITE_BASE_URL,timeout: 60000 // 延时时间:60s
    });// 请求拦截器
    axiosInstance.interceptors.request.use((config: InternalAxiosRequestConfig) => {// 添加tokenlet token = useRequeryStoreInfo.getToken;if (token) config.headers["Authorization"] = "Bearer " + token;const key = useRequeryStoreInfo.getRequestKey(config);// 移除旧的请求useRequeryStoreInfo.removeOldRequest(key);// 开始新的请求const controller = new AbortController();config.signal = controller.signal;useRequeryStoreInfo.setRequest(key, controller);return config;},(error) => {return Promise.reject(error);}
    );// 响应拦截器
    axiosInstance.interceptors.response.use((response: AxiosResponse) => {// 移除完成的请求useRequeryStoreInfo.removeNewRequest(response.config);// 错误处理if (response.data.code != 200) {responseError(response.data.code, response.data.message);return Promise.reject(response.data);}let config = response.config;console.log(`%c${config.baseURL}${config.url} %c${config.method?.toUpperCase()}`, "color:#409EFF; font-weight:bold;", "color:#67C23A; font-weight:bold;");console.log("- 请求参数", config.data, config.params);console.log("- 响应结果", response.data);return Promise.resolve(response.data);},async (error) => {let config = error.config;// 移除完成的请求、不包括主动取消if (error.code !== "ERR_CANCELED" && config) useRequeryStoreInfo.removeNewRequest(error.config);// 错误重试if (config.errorRetry) {const retryTotal: number = config.retryTotal ?? 3;const retryCount: number = config.retryCount ?? 0;if (retryCount < retryTotal) {ElMessage.warning(`请求失败,正在进行第${retryCount + 1}次尝试重新请求...`);config.retryCount = retryCount + 1;await new Promise((resolve) => setTimeout(resolve, 1000));const newController = new AbortController();config.signal = newController.signal;return axiosInstance(config);}}// 错误提示处理if (error.code !== "ERR_CANCELED") {let { message } = error;if (message == "Network Error") message = "连接异常,请稍后重试...";else if (message.includes("timeout")) message = "请求超时,请稍后重试...";ElMessage.error(message || "未知错误,请联系管理员!");}return Promise.reject(error);}
    );// 响应错误处理
    const responseError = (code: number, message: string) => {switch (code) {case 401:if (isLogoutShowing) return;isLogoutShowing = true;ElMessageBox.confirm("登录过期,是否重新登录?", "Warning", {confirmButtonText: "重新登录",cancelButtonText: "取消",type: "warning"}).then(() => {useRequeryStoreInfo.logout();}).finally(() => {isLogoutShowing = false;});break;default:ElMessage.error(message || "未知错误,请联系管理员!");break;}
    };
    export default axiosInstance;
    
  2. 在store\request.ts中:

    import { defineStore } from "pinia";
    import { MD5 } from "crypto-js";
    import router from "@/router";/*** 网络请求* requestList:网络请求*/
    interface Config {method?: string;url?: string;data?: any;params?: any;
    }
    interface State {token: string;requestList: Map<string, AbortController>;
    }
    export const useRequeryStore = defineStore("requery", {persist: {pick: ["token"]},state: (): State => ({token: "",requestList: new Map()}),getters: {// 获取requestListgetRequestList: (state) => state.requestList,// 获取TokengetToken: (state) => state.token},actions: {// 重新登录logout() {router.push({ name: "login" });localStorage.clear();sessionStorage.clear();},// 设置TokensetToken(token: string) {this.token = token;},/*** 获取请求key* @param {Config} config 需要method, data, url, params数据* @returns {string} key*/getRequestKey(config: Config): string {const { method, url, data, params } = config;let newData = typeof data === "object" ? JSON.stringify(data) : data;let newParams = typeof params === "object" ? JSON.stringify(params) : params;return MD5([method, url, newParams, newData].join("&")).toString();},/*** 取消请求* @param {string} key 通过getRequestKey生成的key* @param {boolean} isMessage 是否需要提示* @param {boolean} message 提示内容*/cancelRequest(key: string, isMessage: boolean = false, message: string = "请勿重复操作!") {if (this.getRequestList.has(key)) {const controller = this.requestList.get(key);if (controller) {controller.abort();this.requestList.delete(key);}if (isMessage) ElMessage.warning(message);}},// 存储请求数据setRequest(key: string, controller: AbortController) {this.requestList.set(key, controller);},// 移除旧的请求removeOldRequest(key: string) {this.cancelRequest(key, true);},// 移除完成的请求removeNewRequest(config: Config) {const key = this.getRequestKey(config);this.getRequestList.delete(key);},/*** 手动取消请求* @param {Config} config 需要method, data, url, params数据,请和请求的时候一模一样*/manualCancelRequest(config: Config) {const key = this.getRequestKey(config);this.cancelRequest(key, true, "成功取消请求!");}}
    });
    
  3. 封装请求接口:在api\login.ts中

    import request from "@/utils/request";// 登录
    export const getLogin = (data?: any) => {return request({url: "/user/login",method: "post",data});
    };
    
  4. 错误重复请求:在api\login.ts中

    import request from "@/utils/request";// 登录
    export const getLogin = (data?: any) => {return request({url: "/user/login",method: "post",data,errorRetry:true,retryTotal:3,});
    };
    

本文来自博客园,作者:小周同学~,转载请注明原文链接:https://www.cnblogs.com/xiaozhou-wuyu/p/19199892

相关新闻

  • 2025 年压敏胶源头厂家最新推荐榜单:覆盖多类型产品且经协会测评的权威甄选指南耐高温压敏胶/环保压敏胶/水性压敏胶/医用压敏胶公司推荐
  • 2025年热门的安全检测检验公司榜单
  • 同城洗车小程序系统:一站式洗车服务解决方案

最新新闻

  • 2026沈阳营业性演出许可证报批代办推荐哪家好 - 速递信息
  • 嵌入式语音录音机实战:基于Speex与MQX RTOS的架构设计与优化
  • 网盘直链下载助手:九大平台高速下载终极指南与完整解决方案
  • FramePack终极指南:如何用AI视频扩散模型创作高质量视频内容
  • 洛雪音乐助手:你的跨平台免费开源音乐管家
  • 5分钟终结乱码烦恼:EncodingChecker让文件编码检测变得如此简单

日新闻

  • Visual C++运行库修复终极指南:5分钟快速解决Windows软件启动错误
  • 手把手教你构建统计局地区经济数据爬虫:从环境搭建到数据持久化全指南
  • 2026多Agent深度解析:用AI团队替代单一模型,四种架构实战落地

周新闻

  • Visual C++运行库修复终极指南:5分钟快速解决Windows软件启动错误
  • 手把手教你构建统计局地区经济数据爬虫:从环境搭建到数据持久化全指南
  • 2026多Agent深度解析:用AI团队替代单一模型,四种架构实战落地

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号