在开发中,我们可能需要使用axios来请求数据,为了方便数据的发送、接收、拦截,我们往往需要进行封装,一个合理的封装设计有利于代码的维护与延申。
设计需求
1.可以对所有请求进行操作
2.可以对含有多种base_URL的请求进行各自操作
3.可以对唯一请求进行各自操作
即以上,所有请求包含了各个base_URL、各个base_URL又包含了各自的具体请求,需要在以上三个阶段对各自的请求进行操作,比如请求响应拦截等。
设计实现 目录结构 环境配置
即可根据不同环境下适应不同的配置,详情可看项目规范(五):环境变量
这里采用第二种方式
let base_URL = ''
if (process.env.NODE_ENV === 'development') {
base_URL = 'https://api.gugudata.com'
} else if (process.env.NODE_ENV === 'production') {
base_URL = 'https://api.gugudata.com'
} else if (process.env.NODE_ENV === 'test') {
base_URL = 'https://api.gugudata.com'
}
export { base_URL }
扩展AxiosRequestConfig的配置
首先由于axios的AxiosRequestConfig类型没有拦截器的配置,所以我们可以自创一个在AxiosRequestConfig类型上进行扩展的类型,通过继承的形式来实现
type.ts
import { AxiosRequestConfig, AxiosResponse } from 'axios'
export interface XYRequestInterceptors {
requestInterceptor?: (config: AxiosRequestConfig) => AxiosRequestConfig
requestInterceptorCatch?: (error: any) => any
responseInterceptor?: (config: AxiosResponse) => AxiosResponse
responseInterceptorCatch?: (error: any) => any
}
export interface XYRequestConfig extends AxiosRequestConfig {
interceptors?: XYRequestInterceptors
}
就是声明了一个自创的XYRequestConfig 类型继承了AxiosRequestConfig类型,并添加上自己声明的拦截器XYRequestInterceptors 类型
规划层级设计
通过创建一个request类作为所有请求,而各自的base_URL作为request的各自实例,在创建实例时引入参数,在request类中通过参数来达到不同的实例不同的配置,在request类中包含了数据请求的request方法,在此方法中又包含了各单独请求调用此方法时的拦截配置。这样就可以实现在各个阶段的控制效果。
request类
import axios from 'axios'
import { AxiosInstance } from 'axios'
import { XYRequestInterceptors, XYRequestConfig } from './type'
class XYRequest {
instance: AxiosInstance
interceptors?: XYRequestInterceptors
constructor(config: XYRequestConfig) {
this.instance = axios.create(config)
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
)
//所有实例的拦截
this.instance.interceptors.request.use(
(config) => {
console.log('所有实例请求成功的拦截')
return config
},
(err) => {
console.log('所有实例请求失败的拦截')
return err
}
)
this.instance.interceptors.response.use(
(res) => {
console.log('所有实例响应成功的拦截')
return res
},
(err) => {
console.log('所有实例响应失败的拦截')
return err
}
)
}
request(config: XYRequestConfig): void {
//对单个请求的拦截
if (config.interceptors?.requestInterceptor) {
config = config.interceptors.requestInterceptor(config)
}
this.instance.request(config).then((res) => {
if (config.interceptors?.responseInterceptor) {
res = config.interceptors.responseInterceptor(res)
}
console.log(res)
})
}
}
可以看到这样request类就可以控制对三种状态进行的拦截操作
对于单独实例,我们只需要在new request的时候传入对应配置即可
import XYRequest from './request'
import { base_URL } from './request/config'
const xyrequest = new XYRequest({
baseURL: base_URL,
interceptors: {
requestInterceptor: (config) => {
console.log('请求拦截成功')
return config
},
responseInterceptorCatch: (err) => {
console.log('请求拦截失败')
return err
},
responseInterceptor: (res) => {
console.log('响应拦截成功')
return res
},
requestInterceptorCatch: (err) => {
console.log('响应拦截失败')
return err
}
}
})
export default xyrequest
对于单独请求,在调用方法时传入对配置即可
import xyrequest from './service'
xyrequest.request({
url: '/news/joke/demo',
interceptors: {
requestInterceptor: (config) => {
console.log('单个请求的成功拦截')
return config
},
responseInterceptor: (res) => {
console.log('单个响应的失败拦截')
return res
}
}
})



