ps: 在开发环境下,语法错误一般会在编辑器中直接抛出,导致程序奔溃,能够得到及时的处理。
可以捕获发生在其子组件树任何位置的 JavaScript 错误,并打印这些错误,同时展示降级 UI.
而并不会渲染那些发生崩溃的子组件树。错误边界可以捕获发生在整个子组件树的渲染期间、生命周期方法以及构造函数中的错误。
引用官方文档实例:
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
// 更新 state 使下一次渲染能够显示降级后的 UI
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
// 你同样可以将错误日志上报给服务器
logErrorToMyService(error, errorInfo);
}
render() {
if (this.state.hasError) {
// 你可以自定义降级后的 UI 并渲染
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
无法捕获到的错误:
事件处理
异步代码(setTimeout或requestAnimationFrame回调函数)
服务端渲染
自身抛出来的错误
const useThrowAsyncError = () => {
const [state, setState] = useState();
return (error) => {
setState(() => throw error)
}
}
使用:引入该hook
throwAsyncError(e)
自己封装hook,然后自己去调用setState throw把错误抛出去,调用setState会重新渲染,就会把错误抛出去,就是在渲染周期内了,errorBoundaries就能捕获到了
vue主要是通过errorCaptured钩子来捕获错误,通过errorHandler处理错误。
errorCaptured是捕获一个来自子孙组件的错误时被调用。
vue.config.errorHandler((err, vm, info) => {
// err错误对象
// vm 发生错误的组件实例
// info 一个包含错误来源信息的字符串
// false 该错误不会继续向上传播
return false
})
只能捕获到同步的代码错误,异步错误需要用到装饰器。
try-catch适合处理一些无法控制的错误,比如网络请求、各种I/O操作等。将代码中有可能发生错误的放在try语句块中,一旦发生异常,就将控制权转交给catch块执行,然后继续执行后续任务,不会阻塞进程。
try{
//可能发生错误代码
} catch (err) {
// 捕获
}
但try中发生的错误及异步任务、语法错误,catch捕获不到
<script>
window.addEventListener('error', (error) => {
console.log('捕获到异常:', error);
}, true)
</script>
<img src="./xxxx.png">
返回的是errorEvent事件对象
js运行时,没有被try.catch捕获到的,一般会在window.onerror中捕获到
/**
* @param {String} message 错误信息
* @param {String} source 出错文件
* @param {Number} lineno 行号
* @param {Number} colno 列号
* @param {Object} error Error对象(对象)
*/
window.onerror = function(message, source, lineno, colno, error) {
console.log('捕获到异常:',{message, source, lineno, colno, error});
return true
}
1.window.onerror 函数只有在返回 true 的时候,异常才不会向上抛出(浏览器接收后报红),否则即使是知道异常的发生控制台还是会显示 Uncaught Error: xxxxx
2.window.onerror 最好写在所有JS脚本的前面,否则有可能捕获不到错误
3.window.onerror无法捕获语法错误
当 Promise 被 reject 且没有 reject 处理器的时候,会触发 unhandledrejection 事件;这可能发生在 window 下,但也可能发生在 Worker 中。发生在promise块中的错误,无论是否catch,都会触发unhandledrejection事件。
window.addEventListener("unhandledrejection", event => {
console.warn(`UNHANDLED PROMISE REJECTION: ${event.reason}`);
});
window.onunhandledrejection=function()=>{}
window.frame[0].onerror = function(message, source) => {}
script Error?当引用第三方script的时候,脚本出现错误,直接提示“script error”。
解决1:设置crossorigin=”anonymous”,在非同源情况下,设置 “anonymous” 关键字将不会通过 cookies,客户端 SSL 证书或 HTTP 认证交换用户凭据。但是这个属性并不是所有浏览器都支持(CORS settings attributes - HTML(超文本标记语言))。
解决2:将第三方脚本方法放在try-catch里。
1.利用 window 对象的 load 和 beforeunload 事件实现了网页崩溃的监控。
不错的文章,推荐阅读:http://jasonjl.me/blog/2015/06/21/taking-action-on-browser-crashes/。
window.addEventListener('load', function () {
sessionStorage.setItem('good_exit', 'pending');
setInterval(function () {
sessionStorage.setItem('time_before_crash', new Date().toString());
}, 1000);
});
window.addEventListener('beforeunload', function () {
sessionStorage.setItem('good_exit', 'true');
});
if(sessionStorage.getItem('good_exit') &&
sessionStorage.getItem('good_exit') !== 'true') {
/*
insert crash logging code here
*/
alert('Hey, welcome back from your crash, looks like you crashed on: ' + sessionStorage.getItem('time_before_crash'));
}
利用img 的 src请求不跨域
function report(error) {
const reportUrl = 'http://xxx/report/'
new Image().src = `${reportUrl}?logs=${error}`
}
ps: img的src和script的src: 原理是相同的,都是利用标签的src属性可以跨域请求的特点,但是不同的是:
使用img标签不能访问服务器返回的响应内容,也就是说只能单向的发送get请求;
而使用script标签实现的jsonp跨域可以将服务器响应文本以函数参数的形式返回,浏览器解析js代码时直接就执行了。
1、可疑代码添加 try…catch
2、全局监控JS异常: window.onerror
3、全局监控静态资源异常: window.addEventListener
4、全局捕获没有 catch 的 promise 异常:unhandledrejection
5、iframe 异常:window.error
6、VUE errorHandler 和 React componentDidCatch
7、监控网页崩溃:window 对象的 load 和 beforeunload
8、Script Error 跨域用 crossOrigin 解决
9、统一错误上报,通过new image().src