目录
前言
一、axios中的常见类型
1. AxiosInstance
2. AxiosRequestConfig
3. AxiosResponse
4. AxiosError
二、axios封装步骤
三、封装后的完整代码
1. 基础封装
2. 高级封装
前言
为了实现统一的网络请求处理和管理,在日常开发中我们常常封装 axios,来实现统一配置、设置请求拦截器和响应拦截器、错误处理等。
TypeScript可以给项目提供类型检查和类型推导,axios请求回来的数据也会受其检查。本文将提供axios结合ts写法的封装步骤和代码。
一、axios中的常见类型
1. AxiosInstance
表示axios请求的配置选项,包括URL、方法、头部、参数等。
2. AxiosRequestConfig
表示一个axios实例的类型,可以用于创建自定义配置的axios实例。
3. AxiosResponse
表示axios响应的数据结构,包括状态码、响应头和响应数据。
4. AxiosError
表示axios请求发生错误时的错误对象,包括错误消息、请求配置和响应信息(如果有)。
注意:如果没有跟类型,ts也会自动推到成相应类型。可以不写,但不能错写。
二、axios封装步骤
1. 安装依赖
在项目根目录下,使用 npm 或 yarn 命令安装 axios 和 @types/axios(用于提供 axios 的类型定义文件)
pnpm install axios @types/axios
复制
2. 创建封装文件
在项目中创建一个新的文件,例如 request.ts
,用于封装 axios。可以根据项目需求结构化地组织这些文件。文件名根据个人习惯来,大都取 axios 、request 、http等。
3. 导入 axios
在 request.ts
文件中导入 axios 模块。
4. 添加默认配置
根据需要,在请求方法中设置默认的请求头、超时时间、响应数据格式等配置项。
5. 定义返回的数据类型
根据后端返回的数据,设置统一的请求结果接口。
6. 添加拦截器
如果需要使用拦截器,可以在 api.ts 文件中定义请求拦截器和响应拦截器,并注册到 axios 中。
7. 封装请求方法
根据项目需求,定义请求方法,例如 GET、POST、PUT、DELETE 等。可以使用泛型来指定请求和响应的数据类型,增加类型安全性。
8. 导出方法/实例
在 request.ts
文件末尾,将封装的请求方法进行导出。
三、封装后的完整代码
1. 基础封装
使用对象字面量方式创建一个单例的axios实例。
// 导入axios和所需的类型 import axios, { AxiosInstance, AxiosError, AxiosResponse, InternalAxiosRequestConfig } from 'axios' // 默认配置 const service: AxiosInstance = axios.create({ baseURL: import.meta.env.VITE_API_BASE || '/' // 设置API的基本URL,默认为根路径 }) // 请求拦截器,对请求配置进行一些处理或设置 service.interceptors.request.use( (config: InternalAxiosRequestConfig) => { return config }, (error: AxiosError) => { return Promise.reject(error) } ) // 响应拦截器,对响应结果进行处理或判断 service.interceptors.response.use( (response: AxiosResponse) => { if (response.status === 200) { return response.data } return Promise.reject() // 如果响应状态不是200,则返回一个拒绝的Promise }, (error: AxiosError) => { return Promise.reject(error) } ) export default service // 导出封装好的axios实例 // 定义结果接口Result export interface Result<T = unknown> { message: string code: number data: T [key: string]: any // 其他任意属性 } export const http = { // 发送GET请求的方法,可指定数据类型T,并返回一个Promise对象,其值为Result<T>类型 get<T = any>(url: string, data?: object): Promise<Result<T>> { return service.get<T, Result<T>>(url, data); }, // 发送POST请求的方法,同样可指定数据类型T,并返回一个Promise对象 post<T = any>(url: string, data?: object): Promise<Result<T>> { return service.post<T, Result<T>>(url, data); }, // 发送PUT请求的方法,同样可指定数据类型T,并返回一个Promise对象 put<T = any>(url: string, data?: object): Promise<Result<T>> { return service.put<T, Result<T>>(url, data); }, // 发送DELETE请求的方法,同样可指定数据类型T,并返回一个Promise对象 delete<T = any>( url: string ): Promise<Result<T>> { return service.delete<T, Result<T>>(url); }, };
复制
2. 高级封装
相比基础封装,高级封装通过类的方式来创建实例,并将请求方法封装在类的原型上。
相比之下,这种方法更加灵活,可以创建多个不同配置的axios实例,也可以在实例中添加其他自定义的方法和属性。此外,高级封装还将请求方法统一封装在一个类中,结构更加清晰,易于维护和扩展。
// 先创建一个类,给类添加1个属性 instance代表axios的实例 构造函数传递配置 config配置比如全局的baseURL timeout import axios from "axios"; import type { AxiosInstance, AxiosError, AxiosResponse, AxiosRequestConfig, } from "axios"; // interface Result<T = any> { // data: T; // success: boolean; // } class Request { // 限制创建的实例必须是axios的实例 private instance: AxiosInstance; // 这个config是不能乱写的,axios对创建的配置有限制的 constructor(config: AxiosRequestConfig) { this.instance = axios.create(config); // 接下来配置axios实例身上的全局配置,比如拦截器 this.instance.interceptors.request.use( (config: AxiosRequestConfig) => { return config; }, (error: AxiosError) => { return Promise.reject(error); } ); this.instance.interceptors.response.use( (response: AxiosResponse) => { return response.data; }, (error: AxiosError) => { return Promise.reject(error); } ); } // 公共方法,因为不知道返回值的类型 fetchData<T>(options: AxiosRequestConfig): Promise<T> { // 将私有的instance上面发请求的操作,封装到这个实例方法request中,这个方法的返回值应该是一个promise对象 return new Promise((resolve, reject) => { this.instance .request<any, T>(options) .then((res) => { resolve(res); }) .catch((err) => { reject(err); }); }); } // 调用上面封装的实例方法request,来实现get / post / delete / put 方法的快捷调用 get<T>(options: AxiosRequestConfig): Promise<T> { return this.fetchData<T>({ ...options, method: "GET" }); } post<T>(options: AxiosRequestConfig): Promise<T> { return this.fetchData({ ...options, method: "POST" }); } put<T>(options: AxiosRequestConfig): Promise<T> { return this.fetchData({ ...options, method: "PUT" }); } delete<T>(options: AxiosRequestConfig): Promise<T> { return this.fetchData({ ...options, method: "DELETE" }); } } // 到处新new出来的实例 export const http = new Request({ baseURL: "https://mock.mengxuegu.com/mock/6323def2b4c53348ed2bc5d7/example", });
复制