Bootstrap

返回流类型接口的错误信息处理

返回流类型接口的错误信息处理

前言

返回流类型接口需要在响应成功回调里拦截,且该接口的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' })
		},
	})
}

;