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})}