JavaScript作为前端开发的核心语言,运行时错误如果得不到妥善处理,很容易导致页面白屏或者功能失效。错误边界就是一种能够捕获子组件树中发生的错误,并且展示兜底内容的机制,在React等框架中有广泛应用,原生JS也有对应的错误捕获方式。

原生JS的错误捕获方式
同步代码错误捕获
对于同步执行的代码,可以使用try...catch语句来捕获错误,这是最基础的错误捕获方式。
try {
// 可能出错的同步代码
const obj = null;
console.log(obj.name); // 这里会抛出TypeError
} catch (error) {
// 捕获到错误后的处理逻辑
console.log('捕获到同步错误:', error.message);
} finally {
// 无论是否出错都会执行的代码
console.log('同步代码执行完毕');
}
异步代码错误捕获
异步代码的错误无法被外层的try...catch捕获,需要针对不同的异步形式做处理。
对于传统的回调函数形式的异步操作,错误通常通过回调的第一个参数传递:
function asyncTask(callback) {
setTimeout(() => {
const error = new Error('异步任务出错');
callback(error, null); // 第一个参数传错误对象
}, 1000);
}
asyncTask((err, result) => {
if (err) {
console.log('捕获到回调异步错误:', err.message);
return;
}
console.log('任务结果:', result);
});
对于Promise,可以使用catch方法捕获错误:
const promiseTask = new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('Promise执行出错'));
}, 1000);
});
promiseTask
.then(result => {
console.log('Promise结果:', result);
})
.catch(error => {
console.log('捕获到Promise错误:', error.message);
});
如果使用async/await语法,可以将其放在try...catch中捕获错误:
async function runAsyncTask() {
try {
const result = await promiseTask;
console.log('await结果:', result);
} catch (error) {
console.log('捕获到async/await错误:', error.message);
}
}
runAsyncTask();
全局错误捕获
如果有些错误没有被局部捕获,可以通过全局错误监听来兜底处理。
浏览器环境下可以监听window的error事件:
window.addEventListener('error', (event) => {
// event.message 是错误信息
// event.filename 是出错的文件
// event.lineno 是出错的行号
console.log('全局捕获到错误:', event.message);
// 可以阻止默认的错误提示
event.preventDefault();
});
对于未处理的Promise错误,可以监听unhandledrejection事件:
window.addEventListener('unhandledrejection', (event) => {
console.log('捕获到未处理的Promise错误:', event.reason);
event.preventDefault();
});
React中的错误边界实现
React 16之后引入了错误边界的概念,本质是一个实现了getDerivedStateFromError或者componentDidCatch生命周期的类组件,能够捕获其子组件树中发生的错误,并且渲染兜底UI。
错误边界组件实现
import React from 'react';
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false, error: null };
}
static getDerivedStateFromError(error) {
// 发生错误时更新state,展示兜底UI
return { hasError: true, error };
}
componentDidCatch(error, errorInfo) {
// 可以上报错误信息到监控系统
console.log('错误边界捕获到错误:', error, errorInfo);
}
render() {
if (this.state.hasError) {
// 自定义兜底UI
return <div>组件出错了,请稍后重试</div>;
}
return this.props.children;
}
}
export default ErrorBoundary;
错误边界的使用
只需要用错误边界组件包裹可能出现错误的子组件即可:
import ErrorBoundary from './ErrorBoundary';
import ProblemComponent from './ProblemComponent';
function App() {
return (
<div>
<h1>我的应用</h1>
<ErrorBoundary>
<ProblemComponent />
</ErrorBoundary>
</div>
);
}
错误捕获的注意事项
- 错误边界只能捕获子组件渲染、生命周期、构造函数中的错误,无法捕获事件处理、异步代码、服务端渲染的错误。
- 事件处理函数中的错误可以用普通的
try...catch捕获,不需要依赖错误边界。 - 全局错误捕获适合做错误上报,不建议用来展示用户提示,因为无法知道错误发生的具体位置。
- 错误边界不要包裹太细粒度的组件,尽量包裹功能模块级别的组件,避免一个小组件出错导致整个页面崩溃。
不同捕获方式的适用场景对比
| 捕获方式 | 适用场景 | 局限性 |
|---|---|---|
| try...catch | 同步代码、async/await异步代码 | 无法捕获外部异步代码、事件回调中的错误 |
| Promise.catch | Promise形式的异步代码 | 只能捕获对应Promise链的错误 |
| 全局error监听 | 未捕获的同步错误兜底 | 无法获取错误发生的具体上下文,不能展示精准兜底UI |
| unhandledrejection监听 | 未处理的Promise错误兜底 | 只能捕获没有被catch的Promise错误 |
| React错误边界 | React子组件树的渲染错误 | 无法捕获事件、异步、服务端渲染的错误 |
JavaScript错误边界错误捕获React_error_boundary修改时间:2026-06-23 23:06:34