1.实现最基础的封装
将其封装为一个类,而不是一个函数的原因是因为类可以创建多个实例,适用范围更广,封装性更强一些。
index.ts
// index.tsimport axios from 'axios'import type { AxiosInstance, AxiosRequestConfig } from 'axios' class ZJRequest {// axios 实例 // 定义一个axion实例属性instance: AxiosInstance// 利用构造函数要求传入使用 ZJRequest类时传入参数constructor(config: AxiosRequestConfig) { // 把axios实例赋给instancethis.instance = axios.create(config)}request(config: AxiosRequestConfig) {return this.instance.request(config)}} export default ZJRequest
2.拦截器封装
首先我们封装一下拦截器,这个拦截器分为三种:
- 类拦截器
- 实例拦截器
- 接口拦截器
接下来我们就分别实现这三个拦截器。
类拦截器
类拦截器比较容易实现,只需要在类中对axios.create()
创建的实例调用interceptors
下的两个拦截器即可,实例代码如下:
// index.tsconstructor(config: AxiosRequestConfig) {this.instance = axios.create(config) // 添加所有的实例都有的拦截器this.instance.interceptors.request.use((config) => {// console.log('所有的实例都有的拦截器:请求拦截成功')if (this.showLoading) {this.loading = ElLoading.service({lock: true,text: '正在请求数据....',background: 'rgba(0,0,0,0.5)'})}return config},(err) => {// console.log('所有的实例都有的拦截器:请求拦截失败')return err})this.instance.interceptors.response.use((res) => {// console.log('所有的实例都有的拦截器:响应拦截成功')// 将loading移除this.loading?.close()// 将loading移除// this.loading?.close()const data = res.dataif (data.returnCode === '-1001') {console.log('请求失败,错误信息')} else {return data}},(err) => {console.log('所有的实例都有的拦截器:响应拦截失败')// 将loading移除this.loading?.close()if (err.response.status === 404) {console.log('404的错误')}return err})}
实例拦截器
实例拦截器是为了保证封装的灵活性,因为每一个实例中的拦截后处理的操作可能是不一样的,所以在定义实例时,允许我们传入拦截器。
首先我们定义一下interface,方便类型提示,代码如下:
constructor(config: HYRequestConfig) {this.instance = axios.create(config)this.showLoading = config.showLoading ?? true // 实例拦截器this.interceptors = config.interceptorsthis.instance.interceptors.request.use(this.interceptors?.requestInterceptor,this.interceptors?.requestInterceptorCatch)this.instance.interceptors.response.use(this.interceptors?.responseInterceptor,this.interceptors?.responseInterceptorCatch)}
接口拦截
request(config: HYRequestConfig): Promise {return new Promise((resolve, reject) => {// 1.单个请求对请求config的处理if (config.interceptors?.requestInterceptor) {config = config.interceptors.requestInterceptor(config)}// 2.判断是否需要显示loadingif (config.showLoading === false) {this.showLoading = config.showLoading}this.instance.request(config).then((res) => {// 1.单个请求对数据的处理if (config.interceptors?.responseInterceptor) {res = config.interceptors.responseInterceptor(res)}// 2.将showLoading设置true, 这样不会影响下一个请求this.showLoading = DEAFULT_LOADING// 3.将结果resolve返回出去resolve(res)}).catch((err) => {// 将showLoading设置true, 这样不会影响下一个请求this.showLoading = DEAFULT_LOADINGreject(err)return err})})}get(config: HYRequestConfig): Promise {return this.request({ ...config, method: 'GET' })}post(config: HYRequestConfig): Promise {return this.request({ ...config, method: 'POST' })}delete(config: HYRequestConfig): Promise {return this.request({ ...config, method: 'DELETE' })}patch(config: HYRequestConfig): Promise {return this.request({ ...config, method: 'PATCH' })}
3.完整的index.ts文件和type.ts
import axios from 'axios'import type { AxiosInstance } from 'axios'//导入自己定义的两个类型import type { HYRequestInterceptors, HYRequestConfig } from './type'import { ElLoading } from 'element-plus/lib/components/loading/index'import { LoadingInstance } from 'element-plus/lib/components/loading/src/loading'const DEAFULT_LOADING = trueclass ZJRequest {instance: AxiosInstanceinterceptors?: HYRequestInterceptorsshowLoading: booleanloading?: LoadingInstanceconstructor(config: HYRequestConfig) {this.instance = axios.create(config)this.showLoading = config.showLoading ?? truethis.interceptors = config.interceptorsthis.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('所有的实例都有的拦截器:请求拦截成功')if (this.showLoading) {this.loading = ElLoading.service({lock: true,text: '正在请求数据....',background: 'rgba(0,0,0,0.5)'})}return config},(err) => {// console.log('所有的实例都有的拦截器:请求拦截失败')return err})this.instance.interceptors.response.use((res) => {// console.log('所有的实例都有的拦截器:响应拦截成功')// 将loading移除this.loading?.close()// 将loading移除// this.loading?.close()const data = res.dataif (data.returnCode === '-1001') {console.log('请求失败,错误信息')} else {return data}},(err) => {console.log('所有的实例都有的拦截器:响应拦截失败')// 将loading移除this.loading?.close()if (err.response.status === 404) {console.log('404的错误')}return err})}request(config: HYRequestConfig): Promise {return new Promise((resolve, reject) => {// 1.单个请求对请求config的处理if (config.interceptors?.requestInterceptor) {config = config.interceptors.requestInterceptor(config)}// 2.判断是否需要显示loadingif (config.showLoading === false) {this.showLoading = config.showLoading}this.instance.request(config).then((res) => {// 1.单个请求对数据的处理if (config.interceptors?.responseInterceptor) {res = config.interceptors.responseInterceptor(res)}// 2.将showLoading设置true, 这样不会影响下一个请求this.showLoading = DEAFULT_LOADING// 3.将结果resolve返回出去resolve(res)}).catch((err) => {// 将showLoading设置true, 这样不会影响下一个请求this.showLoading = DEAFULT_LOADINGreject(err)return err})})}get(config: HYRequestConfig): Promise {return this.request({ ...config, method: 'GET' })}post(config: HYRequestConfig): Promise {return this.request({ ...config, method: 'POST' })}delete(config: HYRequestConfig): Promise {return this.request({ ...config, method: 'DELETE' })}patch(config: HYRequestConfig): Promise {return this.request({ ...config, method: 'PATCH' })}}export default ZJRequest
import type { AxiosRequestConfig, AxiosResponse } from 'axios'export interface HYRequestInterceptors {requestInterceptor?: (config: AxiosRequestConfig) => AxiosRequestConfigrequestInterceptorCatch?: (error: any) => anyresponseInterceptor?: (res: T) => TresponseInterceptorCatch?: (error: any) => any}export interface HYRequestConfig extends AxiosRequestConfig {interceptors?: HYRequestInterceptorsshowLoading?: boolean}
4.在index.js先导入ZJRequest
从config中导入相关的配置
new一个实例
//service统一的出口import ZJRequest from './request'import { BASE_URL, TIME_OUT } from './request/config'import localCache from '@/utils/cache'// export default hyRequest =new HYRequest (){// }const zjRequest = new ZJRequest({baseURL: BASE_URL,timeout: TIME_OUT,// 这是拦截器interceptors: {requestInterceptor: (config) => {// 携带token的拦截const token = localCache.getCache('token')if (token) {// 注意要加这个感叹号,不然会报错config.headers!.Authorization = `Bearer ${token}`}console.log(config)// console.log('请求成功的拦截')return config},requestInterceptorCatch: (err) => {// console.log('请求失败的拦截')return err},responseInterceptor: (res) => {// console.log('响应成功的拦截')return res},responseInterceptorCatch: (err) => {// console.log('响应失败的拦截')return err}}})export default zjRequest
5.测试是否发送请求成功
先定义返回的数据类型文件type.ts
export interface IDataType {code: numberdata: T}
之后对应的请求代码中,可以加入IDataType规范返回的数据类型
export function requestUserInfoById(id: number) {return hyRequest.get({url: LoginAPI.LoginUserInfo + id,showLoading: false})}