运城市网站建设_网站建设公司_会员系统_seo优化
2025/12/17 19:11:20 网站建设 项目流程

本文将封装一个类型安全、结构清晰、易于维护的 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) { // 错误已在拦截器中提示,此处可做额外处理 } }

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询