VUE3 AXIOS 封装
网上找了很多AXIOS的封装但是都不是很满意,后来参考其他人的实现做了改动后特分享出来
http.ts 文件封装
import type { AxiosRequestConfig, AxiosResponse } from 'axios'
import axios from 'axios'
const service = axios.create({
baseURL: import.meta.env.VITE_HOST,
headers: {
'Content-Type': 'application/json'
},
// 是否跨站点访问控制请求
withCredentials: false,
timeout: 30000,
transformRequest: [(data, headers) => {
//Content-Type:"multipart/form-data"
if (headers["Content-Type"] == "application/json") {
data = JSON.stringify(data)
}
return data
}],
validateStatus() {
// 使用async-await,处理reject情况较为繁琐,所以全部返回resolve,在业务代码中处理异常
return true
},
transformResponse: [(data) => {
if (typeof data === 'string' && data.startsWith('{')) {
data = JSON.parse(data)
}
return data
}]
})
// 声明一个 Map 用于存储每个请求的标识 和 取消函数
const pending = new Map()
/**
* 添加请求
* @param {Object} config
*/
const addPending = (config: AxiosRequestConfig) => {
const url = [
config.method,
config.url,
config.params,
config.data
].join('&')
config.cancelToken = config.cancelToken || new axios.CancelToken(cancel => {
if (!pending.has(url)) { // 如果 pending 中不存在当前请求,则添加进去
pending.set(url, cancel)
}
})
}
/**
* 移除请求
* @param {Object} config
*/
const removePending = (config: AxiosRequestConfig) => {
const url = [
config.method,
config.url,
config.params,
config.data
].join('&')
if (pending.has(url)) { // 如果在 pending 中存在当前请求标识,需要取消当前请求,并且移除
const cancel = pending.get(url)
cancel(url)
pending.delete(url)
}
}
/**
* 清空 pending 中的请求(在路由跳转时调用)
*/
export const clearPending = () => {
for (const [url, cancel] of pending) {
cancel(url)
}
pending.clear()
}
/**
* 请求拦截器
*/
service.interceptors.request.use((config: AxiosRequestConfig) => {
removePending(config) // 在请求开始前,对之前的请求做检查取消操作
addPending(config) // 将当前请求添加到 pending 中
let token = localStorage.getItem('__TOKEN__')
if (token && config.headers) {
// 服务端 Bearer JWT 要求 Bearer前缀
config.headers.Authorization = `Bearer ${token}`;
}
return config
},
(error) => {
// 错误抛到业务代码
error.data = {}
error.data.msg = '服务器异常,请联系管理员!'
return Promise.resolve(error)
})
/**
* 响应拦截器
* */
service.interceptors.response.use(
(response: AxiosResponse) => {
removePending(response.config); // 在请求结束后,移除本次请求
const status = response.status
let msg = ''
if (status < 200 || status >= 300) {
// 处理http错误,抛到业务代码
// msg = showStatus(status)
if (typeof response.data === 'string') {
response.data = { msg }
} else {
response.data.msg = msg
}
}
// 续签TOKEN
if (response.headers && response.headers.authorization) {
localStorage.setItem('__TOKEN__', response.headers.authorization)
}
return response
},
(error) => {
if (axios.isCancel(error)) {
console.log('repeated request: ' + error.message)
} else {
// handle error code
// 错误抛到业务代码
error.data = {}
error.data.msg = '请求超时或服务器异常,请检查网络或联系管理员!'
// ElMessage.error(error.data.msg)
}
return Promise.reject(error)
})
export default service
Service封装: MediaService.ts
import Axios from 'http'; import type { HttpResponse } from './HttpResponse'; import type { AxiosProgressEvent } from 'axios'; export class MediaService { /** * 上传文件 */ static async UploadFile(data: any): Promise<HttpResponse<any>> { let fileName = data.file.name; let formData = new FormData(); formData.append('file', data.file, fileName) return Axios('http://localhost:29322/api/...', { method: 'post', headers: { 'Content-Type': 'multipart/form-data' }, responseType: 'json', data: formData, onUploadProgress(args: AxiosProgressEvent) { if (args.total) { data.onProgress({ percent: Math.round((args.loaded / args.total) * 100) }, data.file); } } }); } static async AddLibrary(data: any): Promise<HttpResponse<any>> { return Axios('http://localhost:29322/api/...', { method: 'post', responseType: 'json', data: data }); } }
VUE页面调用参考
import { MediaService } from 'MediaService';
MediaService.AddLibrary(formState).then(res => {
// ...
});
MediaService.UploadFile(data).then(res => {
// ...
});
其他相关文件 HttpResponse.ts
export interface HttpResponse<T> {
status: number
statusText: string
data: {
code: number
message: string
data:T
[key: string]: any
}
}

浙公网安备 33010602011771号