共计 2999 个字符,预计需要花费 8 分钟才能阅读完成。
一、根本封装
import axios from 'axios' | |
import type {AxiosInstance, AxiosRequestConfig} from 'axios' | |
class Request { | |
// axios 实例 | |
instance: AxiosInstance | |
constructor(config: AxiosRequestConfig) {this.instance = axios.create(config) | |
} | |
request(config: AxiosRequestConfig) {return this.instance.request(config) | |
} | |
} | |
export default Request |
二、拦截器封装
1. 类拦截器:在类中对 axios.create()创立的实例调用 interceptors 下的两个拦截器。
// index.ts | |
constructor(config: AxiosRequestConfig) {this.instance = axios.create(config) | |
this.instance.interceptors.request.use((res: AxiosRequestConfig) => {console.log('全局申请拦截器') | |
return res | |
}, | |
(err: any) => err, | |
) | |
this.instance.interceptors.response.use( | |
// 因为咱们接口的数据都在 res.data 下,所以咱们间接返回 res.data | |
(res: AxiosResponse) => {console.log('全局响应拦截器') | |
return res.data | |
}, | |
(err: any) => err, | |
) | |
} |
2. 实例拦截器:保障了封装的灵活性,每一个实例中的拦截器后的解决可能不一样。
拦截器的执行程序为实例申请→类申请→实例响应→类响应;这样能够在申请的时候做一些不同的拦挡。
根底拦挡 | |
// types.ts | |
import type {AxiosRequestConfig, AxiosResponse} from 'axios' | |
export interface RequestInterceptors { | |
// 申请拦挡 | |
requestInterceptors?: (config: AxiosRequestConfig) => AxiosRequestConfig | |
requestInterceptorsCatch?: (err: any) => any | |
// 响应拦挡 | |
responseInterceptors?: (config: AxiosResponse) => AxiosResponse | |
responseInterceptorsCatch?: (err: any) => any | |
} | |
// 自定义传入的参数 | |
export interface RequestConfig extends AxiosRequestConfig {interceptors?: RequestInterceptors} |
定义完根底的拦截器之后,须要革新咱们传入的参数的类型,因为是 axios 提供的 AxiosRequestConfig 是不容许咱们传入拦截器的,所以咱们须要自定义拦截器 RequestConfig,让其继承 AxiosRequestConfig。
// index.ts | |
import axios, {AxiosResponse} from 'axios' | |
import type {AxiosInstance, AxiosRequestConfig} from 'axios' | |
import type {RequestConfig, RequestInterceptors} from './types' | |
class Request { | |
// axios 实例 | |
instance: AxiosInstance | |
// 拦截器对象 | |
interceptorsObj?: RequestInterceptors | |
constructor(config: RequestConfig) {this.instance = axios.create(config) | |
this.interceptorsObj = config.interceptors | |
this.instance.interceptors.request.use((res: AxiosRequestConfig) => {console.log('全局申请拦截器') | |
return res | |
}, | |
(err: any) => err, | |
) | |
// 应用实例拦截器 | |
this.instance.interceptors.request.use( | |
this.interceptorsObj?.requestInterceptors, | |
this.interceptorsObj?.requestInterceptorsCatch, | |
) | |
this.instance.interceptors.response.use( | |
this.interceptorsObj?.responseInterceptors, | |
this.interceptorsObj?.responseInterceptorsCatch, | |
) | |
// 全局响应拦截器保障最初执行 | |
this.instance.interceptors.response.use( | |
// 因为咱们接口的数据都在 res.data 下,所以咱们间接返回 res.data | |
(res: AxiosResponse) => {console.log('全局响应拦截器') | |
return res.data | |
}, | |
(err: any) => err, | |
) | |
} | |
} |
3. 接口拦挡:对繁多接口进行拦挡操作
首先将 AxiosRequestConfig 类型批改为 RequestConfig 容许传递拦截器;在类拦截器中将接口申请的数据进行了返回,也就是说在 request()办法中失去的类型就不是 AxiosRequest 类型。
查看 axios 的 index.d.ts 中对 request() 办法的类型如下:
// type.ts | |
request<T = any, R = AxiosResponse<T>, D = any>(config: AxiosRequestConfig<D>): Promise<R>; | |
也就是说容许咱们传递的类型,从而扭转 request()办法的返回值类型:// index.ts | |
request<T>(config: RequestConfig): Promise<T> {return new Promise((resolve, reject) => { | |
// 如果咱们为单个申请设置拦截器,这里应用单个申请的拦截器 | |
if (config.interceptors?.requestInterceptors) {config = config.interceptors.requestInterceptors(config) | |
} | |
this.instance | |
.request<any, T>(config) | |
.then(res => { | |
// 如果咱们为单个响应设置拦截器,这里应用单个响应的拦截器 | |
if (config.interceptors?.responseInterceptors) {res = config.interceptors.responseInterceptors<T>(res) | |
} | |
resolve(res) | |
}) | |
.catch((err: any) => {reject(err) | |
}) | |
}) | |
} |
申请接口拦挡是最前执行,而响应拦挡是最初执行。
正文完
发表至: typescript
2024-03-05