@twotwoba/vv-cli
Version:
Easily create Vite + React19/Vue3 web/h5/mini-program/chrome-extension projects.
88 lines (77 loc) • 2.11 kB
text/typescript
/**
* 自定义 FetchError 类
* @description 用于统一处理 API 请求错误
*/
export class FetchError extends Error {
status: number
info?: Record<string, unknown>
constructor(message: string, status: number, info?: Record<string, unknown>) {
super(message)
this.name = 'FetchError'
this.status = status
this.info = info
Object.setPrototypeOf(this, FetchError.prototype)
}
is(status: number): boolean {
return this.status === status
}
isUnauthorized(): boolean {
return this.status === 401
}
isForbidden(): boolean {
return this.status === 403
}
isServerError(): boolean {
return this.status >= 500
}
}
/**
* HTTP 状态码对应的错误消息映射
*/
const ERROR_MESSAGES: Record<number, string> = {
400: '请求参数错误',
401: '登录已过期,请重新登录',
403: '请求被拒绝',
404: '请求资源或接口不存在',
405: '请求方法不允许',
408: '请求超时',
429: '请求过于频繁,请稍后再试',
500: '服务器发生异常',
502: '网关错误',
503: '服务暂时不可用',
504: '网关超时'
}
/**
* 解析 HTTP 错误状态码
*/
export function resolveError(code: number, customMessage?: string): string {
if (code === 401) {
// 清除 token
localStorage.removeItem('auth_token')
}
return customMessage ?? ERROR_MESSAGES[code] ?? `【${code}】: 未知异常!`
}
/**
* 业务响应数据结构
*/
interface ApiResponse<T = unknown> {
code: number
data?: T
message?: string
}
/**
* 处理 API 响应数据
*/
export function processData<T = unknown>(response: ApiResponse<T>): T {
if (response.code >= 0 && response.code < 300) {
return response.data as T
}
const message = response.message ?? resolveError(response.code)
throw new FetchError(message, response.code, { response })
}
/**
* 类型守卫
*/
export function isFetchError(error: unknown): error is FetchError {
return error instanceof FetchError
}