一、根本封装
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)
})
})
}
申请接口拦挡是最前执行,而响应拦挡是最初执行。