32 lines
1.7 KiB
TypeScript
32 lines
1.7 KiB
TypeScript
import axios from 'axios'
|
|
|
|
export type ApiErrorKind = 'auth' | 'forbidden' | 'validation' | 'conflict' | 'timeout' | 'server' | 'unknown'
|
|
|
|
export interface NormalizedApiError {
|
|
kind: ApiErrorKind
|
|
status?: number
|
|
code?: number | string
|
|
message: string
|
|
unknownResult: boolean
|
|
}
|
|
|
|
const getResponse = (error: unknown) => (axios.isAxiosError(error) ? error.response : undefined)
|
|
|
|
export const normalizeApiError = (error: unknown): NormalizedApiError => {
|
|
const response = getResponse(error)
|
|
const status = response?.status
|
|
const code = response?.data?.code
|
|
const backendMessage = response?.data?.msg
|
|
const timeout = axios.isAxiosError(error) && error.code === 'ECONNABORTED'
|
|
|
|
if (timeout) {
|
|
return { kind: 'timeout', status, code, message: '请求超时,结果可能未知,请刷新确认', unknownResult: true }
|
|
}
|
|
if (status === 401 || code === 401) return { kind: 'auth', status, code, message: '登录状态已失效,请重新登录', unknownResult: false }
|
|
if (status === 403) return { kind: 'forbidden', status, code, message: '没有执行此操作的权限', unknownResult: false }
|
|
if (status === 400) return { kind: 'validation', status, code, message: backendMessage || '请求参数或业务条件不符合要求', unknownResult: false }
|
|
if (status === 409) return { kind: 'conflict', status, code, message: backendMessage || '数据已发生变化,请刷新后重试', unknownResult: false }
|
|
if (status && status >= 500) return { kind: 'server', status, code, message: '服务器处理失败,请稍后重试', unknownResult: false }
|
|
return { kind: 'unknown', status, code, message: backendMessage || '操作失败,请稍后重试', unknownResult: false }
|
|
}
|