错误处理
初步预览
| 处理异常方式 | 说明 |
|---|---|
| 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>