1.实现最基础的封装
将其封装为一个类,而不是一个函数的原因是因为类可以创建多个实例,适用范围更广,封装性更强一些。
index.ts
// index.ts
import axios from 'axios'
import type { AxiosInstance, AxiosRequestConfig } from 'axios'
class ZJRequest {
// axios 实例
// 定义一个axion实例属性
instance: AxiosInstance
// 利用构造函数要求传入使用 ZJRequest类时传入参数
constructor(config: AxiosRequestConfig) {
// 把axios实例赋给instance
this.instance = axios.create(config)
}
request(config: AxiosRequestConfig) {
return this.instance.request(config)
}
}
export default ZJRequest
2.拦截器封装
首先我们封装一下拦截器,这个拦截器分为三种:
- 类拦截器
- 实例拦截器
- 接口拦截器
接下来我们就分别实现这三个拦截器。
类拦截器
类拦截器比较容易实现,只需要在类中对
axios.create()
创建的实例调用
interceptors
下的两个拦截器即可,实例代码如下:
// index.ts
constructor(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.data
if (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.interceptors
this.instance.interceptors.request.use(
this.interceptors?.requestInterceptor,
this.interceptors?.requestInterceptorCatch
)
this.instance.interceptors.response.use(
this.interceptors?.responseInterceptor,
this.interceptors?.responseInterceptorCatch
)
}
接口拦截
request<T>(config: HYRequestConfig<T>): Promise<T> {
return new Promise((resolve, reject) => {
// 1.单个请求对请求config的处理
if (config.interceptors?.requestInterceptor) {
config = config.interceptors.requestInterceptor(config)
}
// 2.判断是否需要显示loading
if (config.showLoading === false) {
this.showLoading = config.showLoading
}
this.instance
.request<any, T>(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_LOADING
reject(err)
return err
})
})
}
get<T>(config: HYRequestConfig<T>): Promise<T> {
return this.request<T>({ ...config, method: 'GET' })
}
post<T>(config: HYRequestConfig<T>): Promise<T> {
return this.request<T>({ ...config, method: 'POST' })
}
delete<T>(config: HYRequestConfig<T>): Promise<T> {
return this.request<T>({ ...config, method: 'DELETE' })
}
patch<T>(config: HYRequestConfig<T>): Promise<T> {
return this.request<T>({ ...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 = true
class ZJRequest {
instance: AxiosInstance
interceptors?: HYRequestInterceptors
showLoading: boolean
loading?: LoadingInstance
constructor(config: HYRequestConfig) {
this.instance = axios.create(config)
this.showLoading = config.showLoading ?? true
this.interceptors = config.interceptors
this.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.data
if (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<T>(config: HYRequestConfig<T>): Promise<T> {
return new Promise((resolve, reject) => {
// 1.单个请求对请求config的处理
if (config.interceptors?.requestInterceptor) {
config = config.interceptors.requestInterceptor(config)
}
// 2.判断是否需要显示loading
if (config.showLoading === false) {
this.showLoading = config.showLoading
}
this.instance
.request<any, T>(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_LOADING
reject(err)
return err
})
})
}
get<T>(config: HYRequestConfig<T>): Promise<T> {
return this.request<T>({ ...config, method: 'GET' })
}
post<T>(config: HYRequestConfig<T>): Promise<T> {
return this.request<T>({ ...config, method: 'POST' })
}
delete<T>(config: HYRequestConfig<T>): Promise<T> {
return this.request<T>({ ...config, method: 'DELETE' })
}
patch<T>(config: HYRequestConfig<T>): Promise<T> {
return this.request<T>({ ...config, method: 'PATCH' })
}
}
export default ZJRequest
import type { AxiosRequestConfig, AxiosResponse } from 'axios'
export interface HYRequestInterceptors<T = AxiosResponse> {
requestInterceptor?: (config: AxiosRequestConfig) => AxiosRequestConfig
requestInterceptorCatch?: (error: any) => any
responseInterceptor?: (res: T) => T
responseInterceptorCatch?: (error: any) => any
}
export interface HYRequestConfig<T = AxiosResponse> extends AxiosRequestConfig {
interceptors?: HYRequestInterceptors<T>
showLoading?: 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<T = any> {
code: number
data: T
}
之后对应的请求代码中,可以加入IDataType规范返回的数据类型
export function requestUserInfoById(id: number) {
return hyRequest.get<IDataType>({
url: LoginAPI.LoginUserInfo + id,
showLoading: false
})
}
版权归原作者 七小山 所有, 如有侵权,请联系我们删除。