实现功能
- 自定义hooks处理请求/响应拦截
- 实现接口定义
- 对
axiosapi进行封装
版本依赖
"dependencies": {
"axios": "^0.26.1",
"element-plus": "^2.1.8",
"vue": "^3.0.0",
},
代码实现
// src/service/request/config.ts
// 对基础条件进行配置
let BASE_URL = 'http://123.207.32.32:8000/'
const TIME_OUT = 10000
if (process.env.NODE_ENV === 'development') {
BASE_URL = 'http://123.207.32.32:8000/'
} else if (process.env.NODE_ENV === 'production') {
BASE_URL = 'http://123.207.32.32:8000/'
} else {
BASE_URL = 'http://123.207.32.32:8000/'
}
export { BASE_URL, TIME_OUT }
// src/service/request/type.ts
// 定义interface接口
import { AxiosRequestConfig, AxiosResponse } from 'axios'
interface ZRequestInterceptors {
requestInterceptor?: (config: AxiosRequestConfig) => AxiosRequestConfig
requestInterceptorCatcher?: (error: any) => any
// 因为我们在全局响应拦截器里面对数据进行了处理const data = res.data 会导致res的数据类型不再是AxiosResponse 这里暂时改为any
// responseInterceptor?: (res: AxiosResponse) => AxiosResponse
responseInterceptor?: (res: any) => any
responseInterceptorCatcher?: (error: any) => any
}
interface ZRequestConfig extends AxiosRequestConfig {
// 自定义AxiosRequestConfig类型
interceptors?: ZRequestInterceptors // 约束用户传递的数据类型
showLoading?: boolean // 是否展示加载loading
}
export { ZRequestConfig, ZRequestInterceptors }
// src/service/request/index.ts
// 实现axios封装
import axios from 'axios'
import type { AxiosInstance } from 'axios'
import { ElLoading } from 'element-plus'
import type { ZRequestInterceptors, ZRequestConfig } from './type'
import { LoadingInstance } from 'element-plus/es/components/loading/src/loading'
// import 'element-plus/es/components/loading/style/css'
export default class ZRequest {
instance: AxiosInstance
interceptors?: ZRequestInterceptors
showLoading: boolean
loading?: LoadingInstance
constructor(config: ZRequestConfig) {
// config 传进来的配置对象
this.instance = axios.create(config) // 创建axios实例
// 保存基本信息
this.interceptors = config.interceptors // 获取用户传递的拦截器钩子
this.showLoading = true // 默认为true
// 从config中取出coder传入的 封装局部拦截器
this.instance.interceptors.request.use(
this.interceptors?.requestInterceptor,
this.interceptors?.requestInterceptorCatcher
)
this.instance.interceptors.response.use(
this.interceptors?.responseInterceptor,
this.interceptors?.responseInterceptorCatcher
)
// 封装全局拦截器
this.instance.interceptors.request.use(
(config) => {
if (this.showLoading) {
this.loading = ElLoading.service({
lock: true,
text: '加载中...',
fullscreen: true,
background: '#f4f4f4'
})
}
return config
},
(err) => {
return err
}
)
this.instance.interceptors.response.use(
(res) => {
// 将loading移除
this.loading?.close()
const data = res.data
if (data.returnCode === '-1001') {
console.log('请求失败')
} else {
return data
}
},
(err) => {
if (err.response.status === 404) {
console.log('404错误')
// 将loading移除
this.loading?.close()
}
return err
}
)
}
request<T>(config: ZRequestConfig): Promise<T> {
return new Promise((resolve, reject) => {
// 单个请求对coder传入的config进行处理
if (config.interceptors?.requestInterceptor) {
config = config.interceptors.requestInterceptor(config) // 对请求进行拦截
}
// 判断请求接口是否显示loading 不传默认为true
if (!config.showLoading) {
this.showLoading = config.showLoading ? true : false
}
// request默认类型声明 request<T = any, R = AxiosResponse<T>, D = any>(config: AxiosRequestConfig<D>): Promise<R>
this.instance
.request<any, T>(config) // 上边全局拦截器钩子this.instance.interceptors.response.use已经对数据进行const data = res.data处理 但是此处ts推导出request返回值类型仍然是AxiosResponse 类型 正确应该是我们定义接口是的<T>类型
.then((res) => {
// 单个请求对数据的处理 判断是否有请求钩子
if (config.interceptors?.responseInterceptor) {
res = config.interceptors.responseInterceptor(res) // 对请求进行拦截
}
// 将showLoading设置为true 不影响下一个接口请求
this.showLoading = true
resolve(res)
})
.catch((err) => {
console.log('requestError', err)
reject(err)
this.showLoading = true
})
})
}
get<T>(config: ZRequestConfig): Promise<T> {
return this.request<T>({ ...config, method: 'GET' })
}
post<T>(config: ZRequestConfig): Promise<T> {
return this.request<T>({ ...config, method: 'POST' })
}
}
// src/service/index.ts
import ZRequest from './request/index'
import { BASE_URL, TIME_OUT } from './request/config'
export default new ZRequest({
baseURL: BASE_URL,
timeout: TIME_OUT,
interceptors: {
// 对单个baseUrl下的请求进行拦截
requestInterceptor: (config) => {
console.log('请求成功的拦截')
return config
},
requestInterceptorCatcher: (err) => {
console.log('请求失败的拦截')
return err
},
responseInterceptor: (res) => {
console.log('响应成功的拦截')
return res
},
responseInterceptorCatcher: (err) => {
console.log('响应失败的拦截')
return err
}
}
})
使用
// src/main.ts
import zwhRequest from './service/index'
interface DataType {
data: any
returnCode: string
success: boolean
}
zwhRequest
.request<DataType>({
url: '/home/multidata',
method: 'GET',
showLoading: true
})
.then((res) => {
console.log(res)
})
bak:学习来自coderwhy