返回流类型接口的错误信息处理
- 前言
- 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-reassignconfig.headers.Authorization = `Bearer ${token.access_token}`}}return config},(err) => Promise.reject(err)
)service.interceptors.response.use((response: AxiosResponse) => {// isNoAccess = 0Nprogress.done()const { config, data, status, headers } = responseconsole.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-syntaxfor (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: xxxparamsSerializer(params) {return qs.stringify(params, { arrayFormat: 'repeat' })},})
}