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

【axios 拦截器】使用 typescript 封装 axios 拦截器

本文将封装一个类型安全、结构清晰、易于维护的 Axios 拦截器模板,融合 TypeScript 泛型、自定义配置扩展等最佳实践,适用于 Vue 3 / React 等框架

目录结构

request/ ├── index.ts // 封装 axios 拦截器 └── types.ts // 拦截器相关类型声明

类型声明

// types.ts import type { AxiosError, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig, } from 'axios' // 扩展 AxiosRequestConfig 接口,添加自定义配置项 declare module 'axios' { export interface AxiosRequestConfig { showMessage?: boolean showLog?: boolean } } export interface RequestOptions<RequestBody> { url: string params?: Record<string, unknown> method?: AxiosRequestConfig['method'] data?: RequestBody responseType?: AxiosRequestConfig['responseType'] showMessage?: boolean showLog?: boolean } export interface ApiResponse<ResponseData = unknown> { code: number // 请求状态:1表示成功,0表示失败 message: string | null // 状态描述信息 data: ResponseData // 响应数据 } // 拦截器类型定义 export type RequestInterceptor = ( config: InternalAxiosRequestConfig ) => InternalAxiosRequestConfig | Promise<InternalAxiosRequestConfig> export type RequestErrorInterceptor = (error: AxiosError) => Promise<never> export type ResponseInterceptor<T = unknown> = ( response: AxiosResponse<ApiResponse<T>> ) => AxiosResponse<ApiResponse<T>> | Promise<AxiosResponse<ApiResponse<T>>> export type ResponseErrorInterceptor = (error: AxiosError<ApiResponse>) => Promise<never>

1. 扩展 Axios 配置

通过模块声明合并,让 Axios 支持 showMessage 和 showLog 字段,避免类型报错

declare module 'axios' { export interface AxiosRequestConfig { showMessage?: boolean showLog?: boolean } }

2. 定义请求选项与响应结构

export interface RequestOptions<RequestBody> { // 请求的接口地址 url: string // 请求的参数 params?: Record<string, unknown> // 请求的方法 method?: AxiosRequestConfig['method'] // 请求体 (Body参数) data?: RequestBody // 响应的数据类型 responseType?: AxiosRequestConfig['responseType'] // 是否显示提示信息 showMessage?: boolean // 是否在控制台打印日志 showLog?: boolean } export interface ApiResponse<ResponseData = unknown> { code: number // 请求状态:1表示成功,0表示失败 message: string | null // 状态描述信息 data: ResponseData // 响应数据 }

封装拦截器

import type { AxiosInstance, AxiosRequestConfig } from 'axios' import axios from 'axios' import type { ApiResponse, RequestErrorInterceptor, RequestInterceptor, RequestOptions, ResponseErrorInterceptor, ResponseInterceptor, } from './types' const instance: AxiosInstance = axios.create({ baseURL: import.meta.env.VITE_BASE_URL, timeout: 5 * 1000, headers: { 'X-Requested-With': 'XMLHttpRequest', }, }) // 发送请求前的操作 const requestSuccessInterceptor: RequestInterceptor = (config) => { // 可以在这里添加token、请求头处理等逻辑 const token = localStorage.getItem('token') || '' if (token) { config.headers['Authorization'] = `Bearer ${token}` } return config } // 请求错误处理函数:当请求配置错误或手动抛出错误时执行 const requestErrorInterceptor: RequestErrorInterceptor = (error) => { return Promise.reject(error) } // 获取响应后的操作 const responseSuccessInterceptor: ResponseInterceptor = (response) => { // console.log('responseSuccessInterceptor [response]: ', response) if (response.config.responseType === 'blob') { return response } // 处理返回响应后的业务逻辑 if (response.data.code === 0) { if (response.config.showMessage) { // 可以使用 ElMessage 展示错误信息 console.log('ElMessage', response.data.message) } return Promise.reject(response.data.message || '业务逻辑异常') } return response } // 响应错误处理函数:当响应状态码不在 2xx 范围内时触发(304不会触发) const responseErrorInterceptor: ResponseErrorInterceptor = (error) => { // console.log('responseErrorInterceptor [error]: ', error) const message = error.response?.data?.message || error.message || '网络错误' if (error.response?.status === 401) { // 处理未登录逻辑,例如跳转到登录页 return Promise.reject('未登录,跳转到登录页') } return Promise.reject(message) } // 添加请求拦截器 instance.interceptors.request.use(requestSuccessInterceptor, requestErrorInterceptor) // 添加响应拦截器 instance.interceptors.response.use(responseSuccessInterceptor, responseErrorInterceptor) // 请求函数 const request = async <ResponseData = unknown, RequestBody = unknown>({ url, params = {}, showMessage = false, showLog = false, method = 'POST', data = undefined, responseType = 'json', }: RequestOptions<RequestBody>): Promise<ApiResponse<ResponseData>> => { const config: AxiosRequestConfig = { url, method, params, data, responseType, showLog, showMessage, } // 请求日志 if (showLog) { console.log(`[Request] ${method} ${url}`, { params, body: data }) } try { const res = await instance(config) // 响应日志 if (showLog) { console.log(`[Response] ${url}`, res.data) } return res.data } catch (err) { console.error(`请求失败: ${url}`, err) throw err // 重新抛出错误 } } export default request

使用示例

interface LoginRequest { username: string password: string } interface UserInfo { id: number name: string } const login = async () => { try { const res = await request<UserInfo, LoginRequest>({ url: '/auth/login', data: { username: 'admin', password: '123456' }, showMessage: true, showLog: true, }) console.log('登录成功', res.data) } catch (err) { // 错误已在拦截器中提示,此处可做额外处理 } }
http://www.cnnetsun.cn/news/111580.html

相关文章:

  • WAN2.2AllInOne V5:重新定义AI视频生成的“极速创作时代“
  • 开源项目商业化实战:Continue如何构建技术价值与商业回报的完美闭环
  • Yuzu模拟器终极配置指南:从零到60帧的完整优化方案
  • 终极SonarQube代码质量报告自动化解决方案:企业级数据驱动决策指南
  • 开展性能测试步骤
  • Coze工作流实战:从踩坑到精通
  • JSON性能革命:RapidJSON如何用SIMD技术改写C++数据处理格局
  • ImageOptim跨版本兼容性全面解析:从macOS 10.13到最新系统的实战指南
  • Qwen3-30B-A3B-Instruct-2507:小参数激活大智慧的AI新范式
  • 打造极速构建体验:BuildKit配置文件深度调优实战
  • 从线上事故看 Java 系统的真实韧性:为什么它总能撑到最后一刻
  • AI Agent框架终极部署指南:从零到生产环境的完整路径
  • 前端性能优化终极指南:让文件转换体验如丝般顺滑
  • 3步彻底解决Dokploy中.traefik.me证书失效问题
  • MCP AI-102模型评估指标全曝光:为什么你的F1-score总是偏低?
  • 量子模拟器环境搭建陷阱与解决方案(90%新手都会犯的3个错误)
  • 【仅限专业人士】量子机器学习调试内幕(VSCode高级功能首次公开)
  • Monet色彩系统如何让Seal视频下载器实现完美的主题一致性
  • 超强Visio形状库:告别绘图瓶颈的终极解决方案
  • ITPUB 专访|李志宇:在 AGI 的未来版图中,记忆是最有温度的力量
  • 音频分离黑科技:3步实现智能多说话人识别
  • 如何快速掌握pose-search:人体姿态搜索的完整指南
  • Agent性能提升迫在眉睫?,立即掌握这3种Docker级性能加速黑科技
  • Note-Gen图片上传实战:从本地预览到云端同步的完整指南
  • VSCode调试Azure QDK API时总出错?这7个坑你必须避开
  • MCP续证Agent开发考核标准全曝光(权威解读+内部评分细则)
  • Android应用沙盒革命:VirtualApp如何重塑移动多开体验
  • 精通SynthDoG:实战构建百万级多语言文档数据集的完整指南
  • Docker MCP网关错误处理避坑指南:3年生产环境踩过的坑一次性说清
  • Golin网络安全扫描工具:从零开始的完整实战指南