返回流类型接口的错误信息处理
- 前言
- axios拦截器src/utils/request.ts
- 对应接口
前言
返回流类型接口需要在响应成功回调里拦截,且该接口的status始终是200,尽管后端返回的code可能是非2xx,因此返回流类型的接口,其错误信息需要单独处理。
axios拦截器src/utils/request.ts
import axios, { type AxiosResponse } from 'axios'
import { ElMessage } from 'element-plus'
import Nprogress from 'nprogress'
import 'nprogress/nprogress.css'
import { getToken } from '@/utils/token'
import router from '@/router/index'
import { environment } from '@/evn.config'
const service = axios.create({
baseURL: environment.VITE_APP_BASE_URL.includes('http')
? environment.VITE_APP_BASE_URL
: window.location.origin,
})
// 不需要token
const whiteList = ['/auth/oauth/token', '/register']
service.interceptors.request.use(
(config) => {
Nprogress.start()
const unneededToken = whiteList.includes(config.url as string)
if (!unneededToken) {
const token = getToken()
if (token && Object.getOwnPropertyNames(token).length) {
// eslint-disable-next-line no-param-reassign
config.headers.Authorization = `Bearer ${token.access_token}`
}
}
return config
},
(err) => Promise.reject(err)
)
service.interceptors.response.use(
(response: AxiosResponse) => {
// isNoAccess = 0
Nprogress.done()
const { config, data, status, headers } = response
console.log(response, config, data, status, headers, 'response-success')
// 下载和预览
if (
config.url?.includes('downloadBatch') ||
config.url?.includes('previewUrl')
) {
let fileName = ''
if (headers['content-disposition']) {
const arr = headers['content-disposition'].split(';')
// eslint-disable-next-line no-restricted-syntax
for (const item of arr) {
if (item.search('filename') !== -1) {
const arr1 = item.split('=')
fileName = decodeURIComponent(arr1[arr1.length - 1])
break
}
}
} else {
const fileReader: any = new FileReader()
fileReader.readAsText(data, 'utf-8')
fileReader.onload = () => {
const result = JSON.parse(fileReader.result as string)
// 错误提示信息,根据接口返回内容
ElMessage.error(result?.message)
}
}
return {
data: {
data,
fileName,
},
}
}
if (status !== 200) {
ElMessage.error({
message: data.message,
duration: 4000,
})
return Promise.reject(response)
}
// 流接口返回错误处理
// if (!data.code && data.type === 'application/json') {
// const fileReader = new FileReader()
// fileReader.readAsText(data, 'utf-8')
// fileReader.onload = () => {
// const result = JSON.parse(fileReader.result as string)
// ElMessage.error(result.message)
// }
// return null
// }
if (!data.success && data.code) {
ElMessage.error({
message: data.message,
duration: 4000,
})
}
return data
},
(error) => {
Nprogress.done()
console.log(error, 'response-error')
if (error.response?.data.code && error.response?.data.code === '2007') {
// 手动点击退出登录时,系统token过期 不提示信息
if (error.response.config.url !== '/system/user/userLogout') {
ElMessage.error('登录状态过期,请重新登录')
}
const url = router.resolve({
path: '/middleBackLogin',
query: {
loginKey: 'tokenNoAccess',
},
})
window.open(url.href, '_self')
} else {
ElMessage.error({
message: error.message,
duration: 4000,
})
if (error.code === 'ERR_NETWORK') {
// 网络问题 强制清除缓存
localStorage.clear()
// 页面刷新
window.location.reload()
}
}
return Promise.reject(error)
}
)
export default service
对应接口
import request from '@/utils/request'
import type { AxiosResponse } from 'axios'
import qs from 'qs'
/**
* 预览申请
* @returns
*/
export function previewUrl(id: number | string): Promise<AxiosResponse> {
return request({
url: `/datawarehouse-api/resourceApply/previewUrl/${id}`,
responseType: 'blob', // 因为是流文件,所以要指定blob类型 这里响应blob,axios拦截器是无法拦截接口报错的msg的
method: 'get',
})
}
/**
* 下载申请
* @returns
*/
export function downloadBatch(params = {}): Promise<AxiosResponse> {
return request({
url: '/datawarehouse-api/resourceApply/downloadBatch',
responseType: 'blob', // 因为是流文件,所以要指定blob类型
method: 'get',
params,
// paramsSerializer: get请求,处理数组参数
// 传的是:
// ids: [xxx,xxx]
// 负载为:
// ids: xxx
// ids: xxx
paramsSerializer(params) {
return qs.stringify(params, { arrayFormat: 'repeat' })
},
})
}