我们在日常使用axios时都是直接使用axios.request(config)
来发送请求和instance.interceptors.request.use()
来进行响应拦截,
但是如果后期axios这个项目不再维护了,或者我们要换成别的网络请求方式了。这样又怎么办呢?难道我们要一处一处的起修改我们的代码吗?重构我们的请求模块?
这样不仅会给我们带来大量的工作量,而且代码的耦合度太高也会导致代码如果出现bug。 但是如果我们把axios在进行封装,封装出一个axios类,然后只让实例依赖axios,我们要发送请求时就使用我们自己封装的axios类,这样我们在后期要换成其他的网络请求方式时,就只修改我们封装的axios类就可以了。这样既可以降低代码的耦合度,也可以降低我们后期维护代码的工作量
版本
文件目录结果
封装
- 首先我们先声明我们的要使用的参数类型来满足我们的typeScript规则,创建一个types.ts文件来存放我们的代码
// 导入axios里面定义的两个类型AxiosRequestConfig(axios参数传入类型), AxiosResponse(请求类型)
import type { AxiosRequestConfig, AxiosResponse } from 'axios'
// 定义一个ZYRequestInterceptors接口用于增加我们传入的AxiosRequestConfig的请求拦截的类型
export interface ZYRequestInterceptors<T = AxiosResponse> {
// 请求成功
requestInterceptor?: (config: AxiosRequestConfig) => AxiosRequestConfig
// 请求失败
requestInterceptorCatch?: (error: any) => any
// 响应成功
responseInterceptor?: (res: T) => T
// 响应失败
responseInterceptorCatch?: (error: any) => any
}
// 导出ZYRequestConfig给index的ZYRequest类的constructor构造类传入参数是设置传参类型,
// ZYRequestConfig继承AxiosRequestConfig并且包含ZYRequestInterceptors,所以具有AxiosRequestConfig和ZYRequestInterceptors的功能
export interface ZYRequestConfig<T = AxiosResponse> extends AxiosRequestConfig {
interceptors?: ZYRequestInterceptors<T>
}
- 我们先导入axios里面定义的两个类型AxiosRequestConfig(axios参数传入类型),和 AxiosResponse(请求类型)。
- 然后定义一个ZYRequestInterceptors接口用于增加我们传入的AxiosRequestConfig的请求拦截的类型
- 当请求成功时的类型定义requestInterceptor
- 请求失败时的类型定义requestInterceptorCatch
- 响应成功时的类型定义responseInterceptor
- 响应失败时的类型定义responseInterceptorCatch
- 最后我们导出ZYRequestConfig给index的ZYRequest类的constructor构造类传入参数是设置传参类型,
- ZYRequestConfig继承AxiosRequestConfig并且包含ZYRequestInterceptors,所以具有AxiosRequestConfig和ZYRequestInterceptors的功能
封装我们自己的axios类,创建一个index.ts文件来存放我们的代码
//首先先导入我们的axios
import axios from 'axios'
//然后导入我们的axios里面定义的AxiosInstance
import type { AxiosInstance } from 'axios'
// 导入自己定义的两个类型
import type { ZYRequestInterceptors, ZYRequestConfig } from './type'
// 定义一个ZYRequest 类用于发送axion的请求
class ZYRequest {
// 定义一个axion实例属性
instance: AxiosInstance
// 定义一个拦截器属性
interceptors?: ZYRequestInterceptors
// 利用构造函数要求传入使用 ZYRequest类时传入参数
constructor(config: ZYRequestConfig) {
// 把axios实例赋给instance
this.instance = axios.create(config)
// 把传入的拦截器赋值给interceptors
this.interceptors = config.interceptors
// 请求拦截
this.instance.interceptors.request.use(
this.interceptors?.requestInterceptor,
this.interceptors?.requestInterceptorCatch
)
// 响应拦截
this.instance.interceptors.response.use(
this.interceptors?.responseInterceptor,
this.interceptors?.responseInterceptorCatch
)
// 2.添加所有的实例都有的拦截器
// 请求拦截
this.instance.interceptors.request.use(
(config) => {
// console.log('所有的实例都有的拦截器: 请求成功拦截')
return config
},
(err) => {
console.log('所有的实例都有的拦截器: 请求失败拦截')
return err
}
)
// 响应拦截
this.instance.interceptors.response.use(
(res) => {
// console.log('所有的实例都有的拦截器: 响应成功拦截'
const data = res.data
// 对返回的响应返回值进行判断,是否响应成功
if (data.returnCode === '-1001') {
console.log('请求失败~, 错误信息')
} else {
return data
}
},
(err) => {
console.log('所有的实例都有的拦截器: 响应失败拦截')
// 例子: 判断不同的HttpErrorCode显示不同的错误信息
if (err.response.status === 404) {
console.log('404的错误~')
}
return err
}
)
}
request<T = any>(config: ZYRequestConfig<T>): Promise<T> {
return new Promise((resolve, reject) => {
// 1.单个请求对请求config的处理
if (config.interceptors?.requestInterceptor) {
config = config.interceptors.requestInterceptor(config)
}
this.instance
.request<any, T>(config)
.then((res) => {
// 1.单个请求对数据的处理
if (config.interceptors?.responseInterceptor) {
res = config.interceptors.responseInterceptor(res)
}
// 将结果resolve返回出去
resolve(res)
})
.catch((err: any) => {
reject(err)
return err
})
})
}
// 定义发送请求的ts类型
get<T = any>(config: ZYRequestConfig<T>): Promise<T> {
return this.request<T>({ ...config, method: 'GET' })
}
post<T = any>(config: ZYRequestConfig<T>): Promise<T> {
return this.request<T>({ ...config, method: 'POST' })
}
delete<T = any>(config: ZYRequestConfig<T>): Promise<T> {
return this.request<T>({ ...config, method: 'DELETE' })
}
patch<T = any>(config: ZYRequestConfig<T>): Promise<T> {
return this.request<T>({ ...config, method: 'PATCH' })
}
}
export default ZYRequest
- 首先先导入我们的axios
- 然后然导入我们的axios里面定义的AxiosInstance,和自己定义的两个类型 ZYRequestInterceptors, ZYRequestConfig
- 然后我们定义一个ZYRequest类,用于定义我们要发送axion的请求的类
- 然后我们在ZYRequest类里面一个axion实例属性和一个拦截器属性,以防创建多个实例时数据交叉修改,以至于出现bug。
- 然后我们利用构造函数要求我们在使用我们当前这个axios实例时,要求要传入参数,参数类型ZYRequestConfig
- 在构造函数里把axios实例赋给instance,以及把传入的拦截器赋值给interceptors,使用.use把我们接受的请求拦截、响应拦截函数挂载在我们的真实的axios实例上,但是这些拦截只针对于我们创建的实例并不是全局请求。
- 所以我们应该再创建一个全局的响应拦截和请求拦截,这个拦截将添加到所有的请求实例中,以及我们要编写对于的错误处理机制,以增强我们的代码的健壮性
- 最后我们要编写我们的request和get、post、delete、patch请求方法。对单个请求对请求的config进行处理
写在最后
伙伴们,如果你觉得我写的文章对你有帮助就给zayyo点一个赞👍或者关注➕都是对我最大的支持。当然你也可以加我微信:IsZhangjianhao,邀你进我的前端学习交流群,一起学习前端,成为更优秀的工程师~
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 29 天,点击查看活动详情