前端一面:错误处理与全局异常捕获
很多一面会从“你遇到过哪些线上错误、怎么处理的?”切到错误处理这一块。这一篇从同步/异步错误处理、全局异常捕获以及在框架里的做法三个角度梳理一下,并给出几道常见题的参考答案。
同步与异步错误处理
在浏览器中,错误大致可以分为:
- 同步错误:在当前调用栈中抛出的异常,例如访问未定义变量、手动
throw等; - 异步错误:发生在回调、Promise、事件处理等异步路径中的错误。
同步错误可以用 try/catch 捕获:
1try {
2 riskyOperation();
3} catch (e) {
4 console.error("同步错误", e);
5}
异步错误的处理则依赖各自机制:
- 回调风格:在回调参数中约定
error; - Promise:使用
.catch捕获链路上的错误; - async/await:外层用
try/catch包裹await。
典型示例:
1async function main() {
2 try {
3 const res = await fetch("/api");
4 const data = await res.json();
5 } catch (e) {
6 console.error("请求失败", e);
7 }
8}
一面里能把这几个层次说清楚,基本就能展示你对错误处理模型的理解。
全局异常捕获:onerror 与 unhandledrejection
除了局部的 try/catch,很多项目会在入口处做全局异常捕获,用于监控/兜底展示:
window.onerror:捕获未被try/catch捕获的运行时错误;window.onunhandledrejection:捕获未被显式.catch处理的 Promise 拒绝。
示例:
1window.onerror = function (message, source, lineno, colno, error) {
2 // 上报错误信息
3 console.log("全局错误", { message, source, lineno, colno, error });
4};
5
6window.onunhandledrejection = function (event) {
7 console.log("未处理的 Promise 拒绝", event.reason);
8};
注意:
- 这些全局处理更适合作“监控 + 兜底提示”,而不是在其中写复杂业务逻辑;
- 对于跨域脚本,如果未正确设置
crossorigin和服务器Access-Control-Allow-Origin,onerror得到的信息可能被限制(只显示 “Script error.”)。
框架中的错误处理:以 React 为例
在框架中,通常会提供一套更高层的错误处理机制,例如 React 的 Error Boundary:
1class ErrorBoundary extends React.Component {
2 state = { hasError: false };
3
4 static getDerivedStateFromError(error) {
5 return { hasError: true };
6 }
7
8 componentDidCatch(error, info) {
9 // 上报错误
10 console.error("组件错误", error, info);
11 }
12
13 render() {
14 if (this.state.hasError) {
15 return <div>出错了,请稍后再试。</div>;
16 }
17 return this.props.children;
18 }
19}
通过在关键 UI 区域外包一层 Error Boundary,可以:
- 防止单个组件错误导致整个应用白屏;
- 在组件层级捕获错误并上报;
- 给用户一个较为友好的兜底文案。
一面如果涉及 React/Vue,可以简单提一下组件层的错误边界概念。
常见面试题与参考答案
题 1:同步错误和异步错误应该如何分别处理?
参考答案要点:
- 同步错误可以直接用
try/catch捕获; - 异步错误需要跟随异步抽象:
- Promise 使用
.catch或在 async/await 外层用try/catch; - 事件/回调风格通过错误参数或统一封装处理;
- Promise 使用
- 单纯的
try/catch无法捕获已经进入事件循环的异步回调里的错误。
可以补一句:
“我们会在异步入口处尽量统一封装,比如封装
request方法,在内部统一处理错误和重试逻辑。”
题 2:如何在全局捕获未处理的错误?这些机制有什么局限?
参考答案要点:
- 可以通过
window.onerror捕获未处理的运行时错误,通过window.onunhandledrejection捕获未处理的 Promise 拒绝; - 这些全局钩子适合用来做错误监控和兜底提示;
- 局限包括:
- 无法精确区分错误上下文,堆栈可能被压缩/混淆;
- 对跨域脚本,如果未正确设置 CORS 与
crossorigin,错误信息会受限。
题 3:在 React 应用中如何防止一个组件的错误导致整页崩溃?
参考答案要点:
- 可以使用 Error Boundary,在关键组件外层包一层错误边界组件;
- Error Boundary 可以在子组件抛错时捕获错误,渲染兜底 UI,并在
componentDidCatch中上报错误; - 需要注意的是,它只能捕获渲染/生命周期中的错误,无法捕获事件处理器内同步抛出的错误(需要配合其它机制)。
这种问法既考你对错误处理的理解,也考察你对框架内建机制的熟悉程度。