源于coderWhy教学视频思想,对axios做一个简单的小结,再次感谢coderwhy大神
Axios官网(中文):Axios (axios-http.com)
//npm方式
npm install axios
//yarn方式
yarn add axios
复制代码
axios(config)
axios.request(config)
axios.get(config)
axios.post(config)
复制代码
缺点是耦合度太高,相同配置需多次重复,且不灵活
aixos
进行加一层封装,将axios封装为自定义的request
,将来直接使用request来发送网络请求就行,日后想要更换网络请求库,可以直接修改request
层,将一些公共的功能封装在request层,如网络请求头添加Authorization
(即token
),加载loading
效果等等,拦截器可以灵活封装使用Typescript进行封装的一些前置知识梳理
axios(config)
中config
的类型为AxiosRequestConfig
,具体见官网:请求配置 | Axios 中文文档 (axios-http.cn)
常用的有几个:url,method,baseUrl,data,timeout
等
默认配置可以进行升级改造,新建一个接口实现AxiosRequestConfig
,在其中添加一些新的配置
AxiosResponse
---axios
默认的返回值类型,接收泛型T
默认为any
,代表的是实际接收到的返回数据类型,一般会将T
设置为IDataType
。
//一般情况下我们只使用data export interface AxiosResponse<T = any> { data: T; status: number; statusText: string; headers: any; config: AxiosRequestConfig; request?: any; } //一般在使用中,我们会将返回数据类型定义为如下形式 export interface IDataType<T = any> { status: string msg: string data: T } 复制代码
日常使用中,我们不会使用AxiosResponse
作为封装后的返回值数据类型,会提取其中的data
,可以通过在响应成功拦截器中返回result.data
来实现(后面会详细介绍),而data
的类型即为IDataType
request
方法来进行
//T默认是any类型,返回值默认是AxiosResponse<T> request<T = any, R = AxiosResponse<T>> (config: AxiosRequestConfig): Promise<R>; 复制代码
封装后实现的效果如下:
//T即为IDataType类型,返回的是一个Promise<T> xxRequest.get<T>(config: xxRequestConfig<T>): Promise<T> 复制代码
baseURL
和timeout
,属于实例级别配置)
//service/index.ts //使用环境配置 const jjRequest = new JJRequest({ baseURL: process.env.VUE_APP_BASE_URL, timeout: process.env.VUE_APP_TIME_OUT }) 复制代码
查看结果:可以看出结果为AxiosResponse<any>
类型
原生的拦截器位于axiosInstance
实例中,使用方法是(来源官网:拦截器 | Axios 中文文档 (axios-http.cn))
注意:响应成功和响应失败的判别标准,以状态码2xx
为界限,超出的响应失败
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
// 2xx 范围内的状态码都会触发该函数。
// 对响应数据做点什么
return response;
}, function (error) {
// 超出 2xx 范围的状态码都会触发该函数。
// 对响应错误做点什么
return Promise.reject(error);
});
复制代码
全局拦截在JJRequest
的构造函数中实现
//service/request/request.ts
//省略前后部分代码
//....
constructor(config: AxiosRequestConfig) {
this.instance = axios.create(config)
//全局请求拦截
this.instance.interceptors.request.use(
(config) => {
console.log(config)
return config
},
(error) => {
console.log('全局请求失败拦截', error)
}
)
//全局响应拦截
this.instance.interceptors.response.use(
(res) => {
//res为AxiosResponse类型,含有config\data\headers\request\status\statusText属性
console.log(res)
//改造返回的数据类型,即将AxiosResponse的data返回
return res.data
},
(error) => {
console.log('全局响应失败拦截')
console.log(error.request)//
console.log(error.response)
return error
}
)
//加入泛型限定,返回数据类型为T,
request<T>(config: AxiosRequestConfig<T>): Promise<T> {
return new Promise<T>((resolve, reject) => {
this.instance
.request<any, T>(config)
.then((res) => {
resolve(res)
})
.catch((err) => {
reject(err)
})
})
}
}
复制代码
实际使用时如下
//main.ts==>返回的数据类型限定为IDataType
jjRequest
.request<IDataType>({
url: '/xxx'
})
.then((res) => {
console.log(res)
})
.catch((err) => {
console.log('=====', err)
})
复制代码
同封装一的接口在main.ts
中运行后效果如下,只剩下AxiosResponse
中的data
,此处为自定义的IDataType
类型,暂时还未明确加入泛型,后面会加入
演示响应失败的拦截:(将后端接口中的/xxx
改为了/xxxx
,则前端访问/xxx
将出现响应失败404
)
需实现的效果如下:
//service/index.ts
const jjRequest = new JJRequest({
baseURL: process.env.VUE_APP_BASE_URL,
timeout: process.env.VUE_APP_TIME_OUT,
//实例级别的拦截器,在创建axios实例的时候携带拦截器
interceptors:{
requestInterceptor: ...
requestInterceptorCatch: ...
responseInterceptor: ...
responseInterceptorCatch: ...
}
})
复制代码
因为原生的AxiosRequestConfig
中没有拦截器配置这个属性,因此需要自定义改造,一是自定义拦截器接口,二是自定义请求配置接口
结果展示
实现调用级别的拦截,需要在request
方法中做文章,将其参数类型也由AxiosRequestConfig
升级为IJJRequestConfig
,实现的思路是直接调用该方法
//service/request/request.ts
//...
request<T>(config: IJJRequestConfig<T>): Promise<T> {
return new Promise<T>((resolve, reject) => {
//请求拦截设置位置
if (config.interceptors?.requestInterceptor) {
config = config.interceptors.requestInterceptor(config)
}
this.instance
.request<any, T>(config)
.then((res) => {
//响应拦截设置位置
if (config.interceptors?.responseInterceptor) {
res = config.interceptors.responseInterceptor(res)
}
resolve(res)
})
.catch((err) => {
console.log('=====', err)
reject(err)
})
})
}
复制代码
调用时如下
jjRequest
.request<IDataType>({
url: '/xxx',
//单个请求调用级别单独设置拦截器
interceptors: {
//直接返回IDataType类型结果中的data属性项
responseInterceptor: (res) => res.data
}
})
.then((res) => {
console.log(res)
})
.catch((err) => {
console.log('=====', err)
})
复制代码
结果如下
//service/request/request.ts
//....
get<T = any>(config: IJJRequestConfig<T>): Promise<T> {
return this.request<T>({
...config,
method: 'GET'
})
}
post<T = any>(config: IJJDRequestConfig<T>): Promise<T> {
return this.request<T>({
...config,
method: 'POST'
})
}
//其余patch、delete等参照一样的,实际调用时可直接使用jjRequest.get<IDataType>(config)来请求数据
复制代码
对
axios
的封装划分了三层
将来可以根据实际情况做相应的封装,主要考虑的是将封装放在哪一层来做,本文主要是写一写封装的思想
例如loading
加载效果,可以在全局来做,也可以在实例层来做,也可以在单个请求处来做,看具体需求!此处就不在做具体的封装,仅做抛砖引玉的作用!
对于axios的封装还有很多,比如关于重复请求的封装、参数序列化等,按需进行即可。ps:主要是我还不会,哈哈。。
来自一个业余程序爱好者小弟的小结,不足之处,请各位大佬指正!
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有