当前位置: 首页 > news >正文

二次封装axios解决异步通信痛点

为了方便扩展,和增加配置的灵活性,这里将通过封装一个类来实现axios的二次封装,要实现的功能包括:

  1. 为请求传入自定义的配置,控制单次请求的不同行为
  2. 在响应拦截器中对业务逻辑进行处理,根据业务约定的成功数据结构,返回业务数据
  3. 对响应错误进行处理,配置显示对话框或消息形式的错误提示
  4. 显示全局的loading
  5. 给get请求加入时间戳,避免缓存
  6. 取消重复的请求
  7. 给请求携带token
  8. token过期时,根据配置决定退出登录或挂起未完成的请求,先去请求更新token的接口,成功后执行挂起的请求
  9. 遇到浏览器返回特定code码,重新发起请求
  10. 路由切换时可以取消未完成的请求
pnpm add axios qs lodash-es

目录

  • 整体结构
  • 创建axios实例
  • 存放多个系统api获取token、更换token的方法
  • 扩展axios类型
  • 自定义的默认请求配置
  • 工具函数
  • 二次封装axios
  • 请求拦截器的处理
  • 响应处理
    • 响应正确的处理
    • 响应错误的处理

整体结构

service/

├── apis 存放api接口,方便统一管理
├── axios
│ ├── axios.d.ts 扩展axios类型
│ ├── config.ts 自定义的配置
│ ├── index.ts 二次封装axios
│ ├── requestInterceptors.ts 处理请求拦截
│ ├── responseInterceptors.ts 处理响应拦截
│ └── utils.ts 工具函数
├── index.ts 创建axios实例
├── tokenManager.ts 存放多个系统api获取token、更换token的方法

创建axios实例

index.ts

import HttpService from './axios'
const service = new HttpService({
   
  baseURL: '/api', // 可根据环境变量配置
  timeout: 3000,
  headers: {
    'Content-Type': 'application/json' }
})
export default service

存放多个系统api获取token、更换token的方法

tokenManager.ts

import {
    useUserStore } from '@/stores/user'
interface System {
   
  tokenKey: string // token 存储的 key
  loginStatus: number // 指定后端返回的code,refreshToken为true时会更新token
  refresh: boolean // token是否自动续期
  getToken: () => string | null
  refreshToken?: (config: any) => Promise<unknown>
  logout: () => void
}
// 存储刷新 token 的请求状态
let isRefreshing = false
// 存储挂起的请求列表
let requests: ((token: string) => void)[] = []

export const SYSTEMS: {
    [key: string]: System } = {
   
  admin: {
   
    tokenKey: 'token',
    loginStatus: 401,
    refresh: true,
    getToken: () => {
   
      const userStore = useUserStore()
      return userStore.getToken
    },
    refreshToken: async (config: any) => {
   
      try {
   
        if (!isRefreshing) {
   
          isRefreshing = true // 标记正在刷新 token
          const userStore = useUserStore()
          const newToken: string = await userStore.refreshToken() // 刷新token
          if (newToken) {
   
            requests.forEach((callback) => callback(newToken)) // 执行挂起的请求
            requests = []
            config.headers[SYSTEMS.admin.tokenKey] = newToken // 附加 token 到请求头
            isRefreshing = false // 标记刷新 token 结束
            return newToken
          } else {
   
            userStore.logout() // 退出登录
            throw new Error('Token 刷新失败')
          }
        }
        // 将本次请求加入挂起队列,并返回一个 Promise,在 refresh token 成功后执行
        return new Promise((resolve) => {
   
          requests.push(() => {
   
            resolve(config)
          })
        })
      } catch (error) {
   
        console.error('刷新 token 失败:', error)
        return Promise.reject(error)
      }finally {
   
        isRefreshing = false; // 标记刷新 token 结束
      }
    },
    logout: () => {
   
      const userStore = useUserStore()
      userStore.logout()
    }
  },
  user: {
   
    tokenKey: 'x-token',
    loginStatus: 401, // 指定后端返回的code,refreshToken为true时会更新token
    refresh: false, // token是否自动续期
    getToken: () => {
   
      return localStorage.getItem('x-token')
    },
    logout: () => {
   
      localStorage.removeItem('x-token')
    }
  }
}

// 更换token
export const refreshToken = async (config: any, systemCode: string) => {
   
  if (SYSTEMS[systemCode] && typeof SYSTEMS[systemCode].refreshToken === 'function') {
   
    return SYSTEMS[systemCode].refreshToken(config)
  } else {
   
    throw new Error(`系统 ${
     systemCode} 对应的刷新token方法未定义`)
  }
}
// 获取token
export 

相关文章:

  • Electron 全面解析:跨平台桌面应用开发指南
  • Web前端开发--HTML
  • css: 针对属性left/right/top/bottom为啥设置transition动画不起作用
  • Mysql中使用sql语句生成雪花算法Id
  • Linux内核模块参数与性能优化:__read_mostly属性的深度剖析
  • 前端开发所需参考文档—重中之中
  • postman登录cookie设置
  • 【目标检测xml2txt】label从VOC格式xml文件转YOLO格式txt文件
  • 利用IDEA将Java.class文件反编译为Java文件:原理、实践与深度解析
  • 建筑兔零基础自学python记录18|实战人脸识别项目——视频检测07
  • Docker 部署 MongoDB | 国内阿里镜像
  • 大模型Deepseek的使用_基于阿里云百炼和Chatbox
  • 全面解析鸿蒙(HarmonyOS)开发:从入门到实战,构建万物互联新时代
  • rabbitmq详解
  • VLLM历次会议(2024.4)
  • vue2老版本 npm install 安装失败_安装卡主
  • 【PL/SQL】常用操作复习20250212
  • 大型语言模型的核心机制解析
  • 随着人们网络安全意识提高,软件架构设计与评估也成为重中之重
  • 新一代SCADA: 宏集Panorama Suite 2025 正式发布,提供更灵活、符合人体工学且安全的应用体验
  • 今年前4个月上海对拉美国家进出口总值增长2%
  • 落实中美经贸高层会谈重要共识,中方调整对美加征关税措施
  • 泽连斯基:将带领乌代表团前往土耳其,已准备好与普京会谈
  • 四部门:到2025年底,全国行政村5G通达率超过90%
  • 印称印巴军事行动总指挥同意将局势降级
  • 全国层面首次!《防震减灾基本知识与技能大纲》发布