1. 前端错误处理:从崩溃到优雅降级的实战指南
凌晨三点的办公室,咖啡已经凉透,屏幕上闪烁的红色错误提示像是一张嘲笑的脸。Cannot read properties of undefined——这个看似简单的错误已经折磨了你两个小时。这不是虚构的场景,而是每个前端开发者都经历过的真实噩梦。
错误处理不是锦上添花的功能,而是现代前端开发的生存技能。根据Sentry的年度报告,超过60%的用户会在遇到页面错误后直接离开,而良好的错误处理可以将用户留存率提升3倍以上。
1.1 为什么前端错误处理如此重要?
想象一下这样的场景:用户正在你的电商网站结账,点击"支付"按钮后页面突然白屏。没有提示,没有解释,只有一片空白。这种情况下,用户不仅会放弃当前交易,很可能永远不会再回来。
前端错误处理的本质是防御性编程的实践。与后端不同,前端运行在不可控的环境中:
- 用户可能使用各种奇怪的浏览器和设备
- 网络连接可能随时中断
- 第三方脚本可能意外崩溃
- API返回的数据结构可能与预期不符
良好的错误处理系统就像飞机的黑匣子+安全气囊组合:既能记录问题发生时的完整上下文,又能在崩溃时保护用户体验不彻底崩溃。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 全局错误捕获:构建你的安全网
2.1 window.onerror:最后的防线
window.onerror是JavaScript最基础的错误捕获机制,可以捕获大多数同步错误。但它的API设计相当反直觉:
javascript复制window.onerror = function(message, source, lineno, colno, error) {
// message: 错误信息字符串
// source: 发生错误的脚本URL
// lineno: 行号
// colno: 列号
// error: Error对象(包含堆栈信息)
// 返回true可以阻止错误在控制台显示
return false;
};
实际项目中,我们需要更健壮的处理:
javascript复制window.onerror = function(msg, url, line, col, error) {
// 过滤浏览器插件错误
if (url?.includes('chrome-extension')) return true;
const errorInfo = {
type: 'javascript',
message: msg,
filename: url,
position: `${line}:${col}`,
stack: error?.stack,
userAgent: navigator.userAgent,
timestamp: new Date().toISOString()
};
// 上报到监控系统
reportError(errorInfo);
return false; // 开发环境保持控制台可见
};
常见陷阱:
- 跨域脚本错误只会显示"Script error",需要添加
crossorigin属性 - 某些浏览器对colno的支持不一致
- 无法捕获资源加载失败(如图片、CSS)
2.2 unhandledrejection:Promise错误的救星
随着async/await的普及,Promise rejection成为前端主要错误来源之一。全局捕获方案:
javascript复制window.addEventListener('unhandledrejection', event => {
const reason = event.reason;
let message = 'Unhandled Promise Rejection';
let stack = '';
if (reason instanceof Error) {
message = reason.message;
stack = reason.stack;
} else {
try {
message = JSON.stringify(reason);
} catch {
message = String(reason);
}
}
reportError({
type: 'promise',
message,
stack,
timestamp: new Date().toISOString()
});
});
关键点:
event.reason可能是任何类型(Error对象、字符串、甚至undefined)- 生产环境不要使用
event.preventDefault(),否则会隐藏控制台错误 - 配合
rejectionhandled事件可以追踪后来被处理的rejection
3. 框架级错误处理
3.1 React错误边界(Error Boundary)
React 16+引入了错误边界概念,允许组件树部分崩溃而不影响整个应用:
jsx复制class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError() {
return { hasError: true };
