概要
在web开发中,常需要使用axios进行网络请求为了防止axios不再维护时出现了bug因此为了增加项目的安全性对axios进行二次封装,当axios不再维护即可选择换一个库迅速重新使用项目
整体架构流程
本文的axios二次封装采用TS的技术栈,通过对request的细节封装后,对get、patch等方法封装,对每一个类创建的实例和每一次的单一请求的拦截器都进行的封装,增强了原生axios的功能
代码细节
- 封装代码
import axios from "axios";
import type {
AxiosInstance, AxiosRequestConfig, AxiosRequestHeaders, AxiosResponse, CreateAxiosDefaults, InternalAxiosRequestConfig } from "axios";
// 针对CreateAxiosDefaults配置进行扩展
// 使其可以添加对应的拦截器来使用
interface DCRequestConfig<T = AxiosResponse> extends CreateAxiosDefaults{
interceptors?: {
requestSuccessFn?: (config: InternalAxiosRequestConfig) => InternalAxiosRequestConfig
requestFailureFn?: (err: any) => any
responseSuccessFn?: (res: T) => T
responseFailureFn?: (err: any) => any
}
}
// 定义单一网络请求时的类型
interface newDCRequestConfig<T = AxiosResponse> extends AxiosRequestConfig{
interceptors?: {
requestSuccessFn?: (config: any) => any
requestFailureFn?: (err: any) => any
responseSuccessFn?: (res: T) => T
responseFailureFn?: (err: any) => any
}
}
class DCRequest {
public instance: AxiosInstance;
// request实例 => axios实例
constructor(config: DCRequestConfig) {
this.instance = axios.create(config);
// 每个instance实例都添加拦截器
// 请求成功和失败的拦截
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.data
}, err => {
console.log('全局的响应失败的拦截');
return err
})
// 针对特定的request实例添加拦截器
if(config.interceptors){
this.instance.interceptors.request.use(
config.interceptors.requestSuccessFn,
config.interceptors.requestFailureFn
)
this.instance.interceptors.response.use(
config.interceptors.responseSuccessFn,
config.interceptors.responseFailureFn
)
}
}
// 封装网络请求方法
request<T = any>(config: newDCRequestConfig<T>) {
if(config.interceptors?.requestSuccessFn) {
// 单次请求成功的拦截
config = config.interceptors.requestSuccessFn(config)
}
return new Promise<T>((resolve, reject) => {
this.instance.request<any, T>(config).then(res => {
// 单次响应成功的拦截
if(config.interceptors?.responseSuccessFn){
res = config.interceptors.responseSuccessFn(res)
}
resolve(res)
}).catch(err => {
reject(err)
})
})
}
get<T = any>(config: newDCRequestConfig<T>) {
return this.request({
...config, method: "GET" })
}
post<T = any>(config: newDCRequestConfig<T>) {
return this.request({
...config, method: "POST" })
}
delete<T = any>(config: newDCRequestConfig<T>) {
return this.request({
...config, method: "DELETE" })
}
patch<T = any>(config: newDCRequestConfig<T>) {
return this.request({
...config, method: "PATCH" })
}
}
export default DCRequest;
- 使用二次封装的axios
import DCRequest from "./request";
const dcRequest = new DCRequest({
baseURL: 'http://codercba.com:8000',
timeout: 10000,
interceptors: {
requestSuccessFn: (config) => {
console.log('单一请求成功的拦截');
return config
},
requestFailureFn: (err) => {
return err
},
responseSuccessFn: (res) => {
console.log('单一响应成功的拦截');
return res
},
responseFailureFn: (err) => {
return err
}
}
})
export default dcRequest
import dcRequest from "..";
interface IInfo {
data: any
returnCode: string,
success: boolean
}
dcRequest.request<IInfo>({
url: '/home/multidata',
interceptors: {
requestSuccessFn: (config) => {
console.log('请求成功的拦截');
return config
},
responseSuccessFn: (res) => {
console.log('应成功的拦截');
return res
}
}
}).then(res => {
console.log(res);
})
小结
作者水平有限,由于拦截器的 InternalAxiosRequestConfig中的headers类型不兼容于AxiosRequestConfig的hedaers请求,想过在定义newDCRequestConfig类型时,把headers类型转化为InternalAxiosRequestConfig中的headers类型,但始终觉得不妥,望有大神可以提供方法
如果本文对你有帮助,麻烦点个赞和关注,谢谢