You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
5.7 KiB
5.7 KiB
前端错误处理工具函数
日期: 2026-01-27
类型: 功能增强
影响范围: 错误处理、用户体验
变更概述
创建统一的错误处理工具函数,简化前端错误处理逻辑,适配后端统一响应格式。
问题背景
前端代码中错误处理不统一:
// 各种不同的错误处理方式
error.response?.data?.detail
error.response?.data?.message
error.message
这导致:
- 代码重复
- 容易遗漏错误消息
- 难以适配新的响应格式
解决方案
创建错误处理工具函数
文件: client/src/lib/error-utils.ts
1. 提取错误消息
export function getErrorMessage(
error: unknown,
fallback = '操作失败,请稍后重试'
): string
使用示例:
try {
await apiClient.post('/auth/login/phone', data);
} catch (error) {
toast({
variant: 'destructive',
title: '登录失败',
description: getErrorMessage(error, '请检查手机号和验证码'),
});
}
2. 获取错误状态码
export function getErrorCode(error: unknown): number | undefined
使用示例:
const code = getErrorCode(error);
if (code === 401) {
// 跳转登录
}
3. 获取错误详情
export function getErrorData(error: unknown): any
使用示例:
const data = getErrorData(error);
if (data?.errors) {
// 显示验证错误详情
}
4. 错误类型判断
export function isAuthError(error: unknown): boolean // 401/403
export function isValidationError(error: unknown): boolean // 422
export function isRateLimitError(error: unknown): boolean // 429
使用示例:
if (isValidationError(error)) {
const errors = formatValidationErrors(error);
// 显示字段级错误
}
5. 格式化验证错误
export function formatValidationErrors(error: unknown): string[]
使用示例:
const errors = formatValidationErrors(error);
// ["body -> code: Field required", "body -> phone: Invalid format"]
适配统一响应格式
工具函数自动适配新旧两种格式:
新格式(RFC-135)
{
success: false,
code: 400,
message: "验证码错误",
data: null,
timestamp: "2026-01-27T08:00:00Z"
}
// 响应拦截器转换后
error.message = "验证码错误"
error.code = 400
error.data = null
旧格式(兼容)
{
detail: "验证码错误"
}
// 工具函数兼容处理
getErrorMessage(error) // → "验证码错误"
使用指南
基础用法
import { getErrorMessage } from '@/lib/error-utils';
try {
await someApiCall();
} catch (error) {
// 简单场景:只显示错误消息
toast({
variant: 'destructive',
description: getErrorMessage(error),
});
}
高级用法
import {
getErrorMessage,
getErrorCode,
isValidationError,
formatValidationErrors
} from '@/lib/error-utils';
try {
await someApiCall();
} catch (error) {
const code = getErrorCode(error);
// 参数验证错误:显示详细字段错误
if (isValidationError(error)) {
const errors = formatValidationErrors(error);
errors.forEach(err => {
toast({ description: err });
});
return;
}
// 其他错误:显示通用消息
toast({
variant: 'destructive',
title: `错误 ${code}`,
description: getErrorMessage(error),
});
}
React Hook Form 集成
import { getErrorMessage } from '@/lib/error-utils';
const onSubmit = async (data: FormData) => {
try {
await apiClient.post('/api/endpoint', data);
} catch (error) {
// 设置表单错误
form.setError('root', {
message: getErrorMessage(error),
});
}
};
已更新文件
- ✅
client/src/pages/LoginPage.tsx- 登录页面错误处理
待更新文件
以下文件仍使用旧的错误处理方式,建议逐步迁移:
client/src/components/common/EditProfileModal.tsxclient/src/components/features/project/CreateProjectModal.tsxclient/src/components/features/project/CreateFolderModal.tsxclient/src/components/features/project/DeleteConfirmModal.tsxclient/src/components/features/project/CloneFolderModal.tsxclient/src/components/features/project/MoveFolderModal.tsxclient/src/components/features/project/ProjectContextMenu.tsxclient/src/components/common/UserPopover.tsx
迁移指南
替换模式
旧代码:
catch (error: any) {
toast({
description: error.response?.data?.detail || '操作失败',
});
}
新代码:
import { getErrorMessage } from '@/lib/error-utils';
catch (error) {
toast({
description: getErrorMessage(error, '操作失败'),
});
}
批量替换建议
- 导入工具函数:
import { getErrorMessage } from '@/lib/error-utils'; - 替换错误消息提取:
error.response?.data?.detail→getErrorMessage(error) - 移除
any类型:catch (error: any)→catch (error)
优势
- 统一性:所有错误处理使用相同的工具函数
- 兼容性:自动适配新旧响应格式
- 类型安全:TypeScript 类型支持
- 可维护性:集中管理错误处理逻辑
- 可扩展性:易于添加新的错误处理功能
相关文档
后续优化
- 逐步迁移所有组件使用新的错误处理工具
- 添加错误追踪和上报功能
- 实现错误重试机制
- 添加错误边界组件集成