参考Vue3+TS+axios封装
以下封装思想来自coderwhy课程
希望在给类YPRequest传入BASE_URL,TIME_OUT的同时,可以传入拦截器
// service 统一出口
import YPRequest from './request'
import { BASE_URL, TIME_OUT } from './request/config'
const ypRequest = new YPRequest({
baseURL: BASE_URL,
timeout: TIME_OUT
//加入拦截器
//hooks:{}
})
// export const ypRequest2 = new YPRequest()
// baseURL:地址一
//这里创造不同的实例,用instance作为区分
export default ypRequest
但是,能直接传入hooks吗?显然是不能的,因为传入YPRequest的参数,是有要求的。
只有下列的参数能传进去
所以为了在new YPRequest创造实例的过程中,添加拦截器,必须自定义类型符合ts的检测。
1.先定义传进来的拦截器的类型
拦截器的本质就是一个个函数
import { AxiosRequestConfig, AxiosResponse } from 'axios'
export interface YPRequestInterceptors {
requestinterceptor?: (config: AxiosRequestConfig) => AxiosRequestConfig
requestinterceptorCatch?: (error: any) => any
responseinterceptor?: (config: AxiosResponse) => AxiosResponse
responseinterceptorCatch?: (error: any) => any
} //定义传入进来的拦截器
requestinterceptor:请求拦截
requestinterceptorCatch:请求失败拦截
responseinterceptor:响应拦截
responseinterceptorCatch响应失败拦截
2.定义接口,取代之前(constructor里的参数必须是AxiosRequestConfig)
export interface YPRequestConfig extends AxiosRequestConfig {
interceptors?: YPRequestInterceptors
}
给他拓展一个interceptors
3.重新拓展类 YPRequest
class YPRequest {
instance: AxiosInstance //instance 用于区分,当有多个请求时,是用不同的实例
interceptors?: YPRequestInterceptors
constructor(config: YPRequestConfig) {
//可以点击config进去看里面的类型
this.instance = axios.create(config)
this.interceptors = config.interceptors
//以下两个ues对传入的拦截器进行调用
this.instance.interceptors.request.use(
this.interceptors?.requestinterceptor,
this.interceptors?.requestinterceptorCatch
) //
this.instance.interceptors.response.use(
this.interceptors?.responseinterceptor,
this.interceptors?.responseinterceptorCatch
)
}
request(config: AxiosRequestConfig): void {
this.instance.request(config).then((res) => {
console.log(res.data)
})
}
}
4.在创建实例时传入拦截器
// service 统一出口
import YPRequest from './request'
import { BASE_URL, TIME_OUT } from './request/config'
const ypRequest = new YPRequest({
baseURL: BASE_URL,
timeout: TIME_OUT,
interceptors: {
//拦截器的本质是传入一个个函数
requestinterceptor: (config) => {
console.log('请求成功的拦截')
return config
},
requestinterceptorCatch: (err) => {
console.log('请求失败的拦截')
return err
},
responseinterceptor: (res) => {
console.log('响应成功的拦截')
return res
},
responseinterceptorCatch: (err) => {
console.log('响应失败的拦截')
return err
}
}
})
// export const ypRequest2 = new YPRequest()
// baseURL:地址一
//这里创造不同的实例,用instance作为区分
export default ypRequest
思路总结:
1.先定义一个class YPRequest类
2.通过new YPRequest可以创造实例ypRequest,同时可以传入BASE_URL,TIME_OUT、拦截器等信息。
3.通过上一步,信息只为上面实例所有。
4.由于写好了request,所以只要调用ypRequest.request(//传入信息)即可
因为一般一个项目只请求一个BASE_URL,所以通常只创建一个实例。
补充,加上全局的拦截器(所有实例都有的拦截器)和 给某一请求添加特定拦截器
// 关于axios的封装,都封装到这个类里面,因为类具备很强的封装性,比函数要强
import axios from 'axios'
import type { AxiosInstance } from 'axios' //axios内部已经提供了关于axios实例的类型
import type { YPRequestInterceptors, YPRequestConfig } from './type'
// interface YPRequestInterceptors {
// requestinterceptor?: (config: AxiosRequestConfig) => AxiosRequestConfig
// requestinterceptorCatch?: (error: any) => any
// responseinterceptor?: (config: AxiosResponse) => AxiosResponse
// responseinterceptorCatch?: (error: any) => any
// } //定义传入进来的拦截器
// interface YPRequestConfig extends AxiosRequestConfig {
// interceptors?: YPRequestInterceptors
// }
class YPRequest {
instance: AxiosInstance //instance 用于区分,当有多个请求时,是用不同的实例
interceptors?: YPRequestInterceptors
constructor(config: YPRequestConfig) {
//可以点击config进去看里面的类型
this.instance = axios.create(config)
this.interceptors = config.interceptors
//从config中取出的拦截器是对应的实例的拦截器
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) => {
return err
}
)
}
request(config: YPRequestConfig): 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.data)
})
}
}
export default YPRequest
//给特定实例拦截器
ypRequest.request({
url: '/home/multidata',
method: 'GET',
interceptors: {
requestinterceptor: (config) => {
console.log('单独成功的拦截')
return config
}
}
})