前端异常错误处理(包括但不限于react,vue)

错误异常发生

  • 页面js报错
  • 请求报错
  • 页面资源加载报错
  • promise异常
  • iframe加载异常
  • 页面奔溃&卡顿异常

处理异常的方法

1、react 自带的errorBoundaries
2、 react 自定义Hooks
3、 vue errorHandler
4、try catch 对特定的代码进行捕获
5、window.addEventListerner
6、window.onerror
7、 window.unhandledrejection
8、 iframe错误处理
9、跨域错误处理
10、页面奔溃卡顿处理
11、 统一上报错误(不会有跨域问题

ps: 在开发环境下,语法错误一般会在编辑器中直接抛出,导致程序奔溃,能够得到及时的处理。

1、react errorBoundaries错误边界

可以捕获发生在其子组件树任何位置的 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回调函数)
服务端渲染
自身抛出来的错误

2、react 自定义Hooks

const useThrowAsyncError = () => {
	const [state, setState] = useState();
	return (error) => {
		setState(() => throw error)
	}
}

使用:引入该hook

throwAsyncError(e)

自己封装hook,然后自己去调用setState throw把错误抛出去,调用setState会重新渲染,就会把错误抛出去,就是在渲染周期内了,errorBoundaries就能捕获到了

3、errorHandler

vue主要是通过errorCaptured钩子来捕获错误,通过errorHandler处理错误。
errorCaptured是捕获一个来自子孙组件的错误时被调用。

vue.config.errorHandler((err, vm, info) => {
	// err错误对象
	// vm 发生错误的组件实例
	// info 一个包含错误来源信息的字符串
	// false 该错误不会继续向上传播
	return false
})

只能捕获到同步的代码错误,异步错误需要用到装饰器。

4、 try catch 对特定的代码进行捕获

try-catch适合处理一些无法控制的错误,比如网络请求、各种I/O操作等。将代码中有可能发生错误的放在try语句块中,一旦发生异常,就将控制权转交给catch块执行,然后继续执行后续任务,不会阻塞进程。

try{
	//可能发生错误代码
} catch (err) {
	// 捕获
}

但try中发生的错误及异步任务、语法错误,catch捕获不到

5、 window.addEventListerner

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

返回的是errorEvent事件对象

6. window.onerror

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无法捕获语法错误

7. unhandledrejection

当 Promise 被 reject 且没有 reject 处理器的时候,会触发 unhandledrejection 事件;这可能发生在 window 下,但也可能发生在 Worker 中。发生在promise块中的错误,无论是否catch,都会触发unhandledrejection事件。

window.addEventListener("unhandledrejection", event => {
  console.warn(`UNHANDLED PROMISE REJECTION: ${event.reason}`);
});

window.onunhandledrejection=function()=>{}

8. iframe错误处理

window.frame[0].onerror = function(message, source) => {}

9、跨域错误处理

script Error?当引用第三方script的时候,脚本出现错误,直接提示“script error”。

解决1:设置crossorigin=”anonymous”,在非同源情况下,设置 “anonymous” 关键字将不会通过 cookies,客户端 SSL 证书或 HTTP 认证交换用户凭据。但是这个属性并不是所有浏览器都支持(CORS settings attributes - HTML(超文本标记语言))。
解决2:将第三方脚本方法放在try-catch里。

10、页面奔溃卡顿处理

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'));
  }

11、统一上报错误(不会有跨域问题)

利用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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值