我们在日常使用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类,创建一个index.ts文件来存放我们的代码
import axios from 'axios'
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