跳到主要内容
版本:Next

错误处理

初步预览

处理异常方式说明
try-catch可预见、可疑区域
window.onerror全局捕获 JavaScript 异常
window.addEventListener全局捕获静态资源异常
Promise catch捕获 Promise 异常,也可使用 unhandledrejection 进行全局捕获
vue errorHandler捕获 vue 异常
react 异常捕获捕获 react 异常
crossOrigin解决 JavaScript 脚本跨域

1.错误原因

1、JavaScript 语法错误、代码异常

2、异步请求异常

3、静态资源加载异常

4、Promise 异常

5、跨域

6、崩溃与渲染异常

2.错误处理方式

1、try-catch

try-catch 无法捕获语法错误和异步错误。

try {
let name = "leo";
console.log(age);
} catch (e) {
console.log("捕获到异常:", e);
}

// 捕获到异常: ReferenceError: age is not defined
try {
let name = 'leo; // 缺少一个单引号,属于语法错误,在开发阶段便提示出来
console.log(age);
} catch(e) {
console.log('捕获到异常:',e);
}
// Uncaught SyntaxError: Invalid or unexpected token

2、window.onerror(同步异步都可捕获)

可以使用 window.onerror 对 JavaScript 运行错误时进行捕获。 无法捕获语法错误

window.onerror 最好写在所有 JavaScript 脚本前面,否则有可能捕获不到异常;

window.onerror 无法捕获语法异常、静态资源异常、接口请求异常;

window.onerror 主要用来捕获意料之外的异常,而 try-catch 则是用来捕获可预见的异常。

/**
* message 错误信息
* source 出错文件
* lineNo 行号
* colNo 列号
* error Error对象(对象)
*/
window.onerror = function (message, source, lineNo, colNo, error) {
console.log("捕获到异常:", { message, source, lineNo, colNo, error });
};

3、window.addEventListener

可以使用 window.addEventListener 对静态资源加载异常与接口请求异常进行捕获。

当一项资源(如图片或脚本)加载失败,加载资源的元素会触发一个 Event 接口的 error 事件,并执行该元素上的 onerror 处理函数。

由于网络请求异常不会事件冒泡,因此必须在捕获阶段将其捕捉到才行,但是这种方式虽然可以捕捉到网络请求的异常,但是无法判断状态码是 404 还是其他比如 500 等等,所以还需要配合服务端日志才进行排查分析才可以。

<scritp>
window.addEventListener('error', (error) => {
console.log('捕获到异常:', error);
}, true)
</script>
<img src="../../assets/test.png">

4、Promise catch

new Promise((resolve, reject) => {
reject("执行失败!");
}).catch((error) => {
console.log("捕获到异常:", error);
});

有时候我们在写 Promise 可能会漏掉 catch,所以建议在全局增加一个对 unhandledrejection 的监听,用来全局监听 Uncaught Promise Error

添加 event.preventDefault(); 可以去掉控制台的异常显示信息。

window.addEventListener("unhandledrejection", function (e) {
e.preventDefault();
console.log("捕获到异常:", e);
});
new Promise((resolve, reject) => {
reject("执行失败!");
});

5、vue errorHandler

Vue.config.errorHandler = (err, vm, info) => {
console.error(err);
console.error(vm);
console.error(info);
};

// 某个组件的 mounted
const error = new Error("test error");
error.code = -1;
throw error;

6、 react 异常捕获

7、跨域

资源跨域可以为 script 标签添加 crossOrigin 属性。

<script src="http://localhost:3000/main.js" crossorigin></script>
// 动态添加
const script = document.createElement("script");
script.crossOrigin = "anonymous";
script.src = url;
document.body.appendChild(script);

3.react 错误边界(仅类组件)

class ErrorBoundary extends React.Component {
// 用于标识子组件是否产生错误
state = { hasError: false }

// 只要这个错误边界组件包裹的后代组件发生错误,就会触发这个钩子,发生的错误信息会作为参数传入
static getDerivedStateFromError(error) {
return { hasError: true }
}

componentDidCatch(error, errorInfo) {
// 可以将错误日志上报给服务器
...
}

render() {
if (this.state.hasError) {
// 可以自定义降级后的 UI 并渲染
return <h1>发生错误了...</h1>
}

return this.props.children;

}
}

// 然后就可以当做一个常规组件去使用
<ErrorBoundary>
<MyWidget />
</ErrorBoundary>