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

news/2025/11/7 15:39:03/文章来源:https://www.cnblogs.com/xiaozhou-wuyu/p/19199892

注意:需要安装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,});
    };
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/958907.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025 年压敏胶源头厂家最新推荐榜单:覆盖多类型产品且经协会测评的权威甄选指南耐高温压敏胶/环保压敏胶/水性压敏胶/医用压敏胶公司推荐

引言 压敏胶作为工业生产关键粘接材料,广泛应用于厨具家电、汽车制造、医疗器材、电子电气等行业。随着市场需求增长,源头厂家数量激增,部分厂家存在生产规模小、技术水平低等问题,导致产品质量不稳定,难以满足企…

window.open()与session

//window.open()打开的新页签会继承父页签的session,在新页签中通过sessionStorage.clear()清除session会同时清除父页签的session //解决方法 // 创建一个具有独立 sessionStorage 的新窗口window.open(url, _blank,…

2025年安全网与遮阳网厂家综合实力Top5

1、诚瑞信 作为行业领军企业,诚瑞信凭借20余年的专业生产经验,在安全网和遮阳网领域展现出卓越的综合实力。公司拥有10000平方米的现代化生产基地,配备30台先进生产设备,年产值达千万级别。产品线涵盖建筑用密目式…

2025年热门的安全检测检验公司榜单

摘要 安全检测检验行业在2025年持续增长,随着矿山安全法规的加强和数字化转型,企业对于可靠检测服务的需求日益提升。本文基于行业数据和用户反馈,整理了市面上前十名安全检测检验公司排名,为矿山企业提供参考。表…

2025年安全检测检验公司排行榜:前十名权威推荐与行业洞察

摘要 安全检测检验行业在2025年持续快速发展,随着矿山安全法规的加强和数字化转型,企业对专业检测服务的需求日益增长。本文基于市场调研和权威数据,整理了市面上安全检测检验公司的排名前十榜单,旨在为矿山企业提…

2025年有实力的安全检测检验公司热门排行前十强榜单

摘要 随着矿山安全意识的提升,安全检测检验行业在2025年迎来快速发展,行业内公司竞争激烈。本文基于行业数据和用户评价,整理了市面上有实力的安全检测检验公司排名前十,旨在为矿山企业提供参考。排名综合考虑了技…

2025年11月四川护栏厂家排名榜:五家实力对比与选购指南

如果您正在四川寻找可长期合作的护栏厂家,大概率正面临“项目工期紧、规格多、预算有限”的三重压力。市政道路升级、河道整治、楼盘阳台交付节点往往集中在年底,一旦供货延迟,牵一发动全身。过去两年,四川住建部门…

2025年11月四川护栏厂家推荐榜:五强产能对比与口碑评价全解析

年底临近,四川各地市政、房建、交安项目进入集中收尾阶段,护栏作为道路、河道、阳台、桥梁的“安全最后一道防线”,采购量陡增。很多工程负责人、开发商、总包单位在同时面对“工期紧、价差大、标准多”的三重压力:…

同城洗车小程序系统:一站式洗车服务解决方案

一、概述总结 同城洗车小程序系统是一款适配微信小程序与支付宝小程序的专业服务工具,支持 PHP7.3 及 PHP7.4 运行环境,以微擎系统在线交付,提供未加密源码保障官方正品权益。系统核心聚焦同城洗车服务的供需对接,…

2025 年物业管理公司服务口碑排行榜权威发布:五标认证企业与精细化服务实力最新推荐政府机构/写字楼/商场/园区物业管理公司服务推荐

引言 随着城市化进程加快,物业管理行业已成为保障生活与工作秩序的核心力量,但行业服务质量两极分化问题显著,头部企业与尾部企业服务得分差距可达 25 分以上。为精准筛选优质企业,行业协会开展专项测评,采用百分…

Tauri跨平台开发:Rust后端+React前端桌面应用实践 - 教程

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

魔方报名缴费系统:高效便捷的全流程报名解决方案

一、概述总结 魔方报名缴费系统是一款基于 PHP+MYSQL 开源技术开发的微信小程序应用,专为学校、事业单位打造成熟、专业且安全的报名缴费全流程解决方案。系统凭借管理精细、贴合行业特征、注重用户体验等优势,在高校…

2025 物业托管公司最新推荐榜:权威测评出炉,,多业态服务实力甄选园区/银行/剧院/商业物业托管公司服务推荐

引言 物业托管行业规模持续扩张,但资质缺失、服务断层等问题仍制约发展。为此,行业协会联合第三方机构开展专项测评,形成最新服务推荐榜单。本次测评采用 SERVQUAL 服务质量差距模型,从有形性、可靠性、响应性、保…

打破孤立的隐形枷锁:AI智能守护如何拯救校园中的“边缘”学生

根据全球心理健康调查,青少年社交退缩率高达20%,不仅侵蚀个体自信,还可能引发次生灾害,如校园群体事件或集体情绪波动。家长们心痛于孩子的“失联”,学校管理者则苦于传统观察的盲区,无法及早察觉。这正是教育领…

文字识别

import os import cv2 import numpy as np import torch import torch.nn as nn import torch.nn.functional as F import torch.optim as optim from torch.utils.data import Dataset, DataLoader from torchvision …

知识付费网盘变现微信小程序系统:资源变现与流量裂变解决方案

一、概述总结 这款知识付费网盘变现微信小程序系统,是基于微擎平台、采用 uniapp 开发的多功能资源变现工具。它核心解决网络资源分享类自媒体的变现与传播难题,通过多元资源获取方式、灵活会员体系和多层级裂变模式…

热血传奇,经典重现,完美传奇游戏详细图文架设教程

经典热血传奇,三职业合击版本,装备三合一进阶,全靠打纯绿服,支持安卓苹果双端,数据互通。前言 这个月给大家带来的是幽冥传奇之《完美传奇》,经典热血传奇,三职业合击版本,装备三合一进阶,全靠打纯绿服,支持…

STM32和ESP32有什么区别?如何选开发板?资深工程师学习路线建议!

在网上搜索“STM32和ESP32的区别”,你可能会得到一堆参数对比:内核、主频、外设、功耗……今天,我们不罗列参数,而是从实际应用、学习路径和职业发展的角度,帮你彻底理清这两大顶流MCU的关系,并为你揭示一条通往…

问题Whitelabel Error Page用Maven方式构建Spring Boot Web

@GetMapping("/hello") http://localhost:8080/hello打开不许是这样子的

TCP/IP 协议族—理论与实践(二) - 指南

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …