前端异常埋点问题

开发者有时会面临上线的生产环境包出现了异常bug,在长期生产bug并修复bug的循环中总结出以下几个痛点:

  1. 无法快速定位到发生错误的代码位置,因为脚手架构建时会用webapck自动帮我们压缩代码,而上线版本又通常不会保留 source map(开源贡献者除外)

  2. 无法第一时间通知开发人员异常发生

  3. 不知道用户OS与浏览器版本、请求参数(如页面ID);而对于页面逻辑是否错误问题,通常除了用户OS与浏览器版本外,需要的是报错的堆栈信息及具体报错位置。

错误埋点追踪系统的出现就是为了应对上述问题的解决方案,针对前端埋点与错误处理的博客内容,按例总结一下。

什么是埋点

大数据时代数据的重要性不言而喻,而其中最重要的就是用户信息的采集。埋点,无论是项目后期的复盘,还是明确业务价值,还是产品价值的挖掘,都具备很重要的意义。

前端异常捕获

在ES3之前js代码执行的过程中,一旦出现错误,整个js代码都会停止执行,这样就显的代码非常的不健壮。从ES3开始,js也提供了类似的异常处理机制,从而让js代码变的更健壮,程序执行的过程中出现了异常,也可以让程序具有了一部分的异常恢复能力。js异常的特点是,出现不会导致JS引擎崩溃,最多只会终止当前执行的任务。

回归正题,我们该如何在程序异常发生时捕捉并进行对应的处理呢?在Javascript中,我们通常有以下两种异常捕获机制。

基本的try…catch语句

  function errFunc() {
      // eslint-disable-next-line no-undef
      error;
  }

  function catchError() {
      try {
          this.errFunc();
      } catch (error) {
          console.log(error);
      }
  }
  catchError()

能捕捉到的异常,必须是线程执行已经进入 try catch 但 try catch 未执行完的时候抛出来的,以下都是无法被捕获到的情形。

  1. 异步任务抛出的异常(执行时try catch已经从执行完了)

  2. promise(异常内部捕获到了,并未往上抛异常,使用catch处理)

  3. 语法错误(代码运行前,在编译时就检查出来了的错误)

  • 优点:能够较好地进行异常捕获,不至于使得页面由于一处错误挂掉

  • 缺点:显得过于臃肿,大多代码使用try ... catch包裹,影响代码可读性。

思考:请用一句话描述 try catch 能捕获到哪些 JS 异常

全局异常监听window.onerror

window.onerror 最大的好处就是同步任务、异步任务都可捕获,可以得到具体的异常信息、异常文件的URL、异常的行号与列号及异常的堆栈信息,再捕获异常后,统一上报至我们的日志服务器,而且可以全局监听,代码看起来也简洁很多。

  • 缺点:

  1. 此方法有一定的浏览器兼容性

  2. 跨域脚本无法准确捕获异常,跨域之后window.onerror捕获不到正确的异常信息,而是统一返回一个Script error,可通过在<script>使用crossorigin属性来规避这个问题

 

window.addEventListener('error'function() {
  console.log(error);
  // ...
  // 异常上报
});
throw new Error('这是一个错误');

Promise内部异常

前文已经提到,onerror 以及 try-catch 也无法捕获Promise实例抛出的异常,只能最后在 catch 函数上处理,但是代码写多了就容易糊涂,忘记写 catch。

如果你的应用用到很多的 Promise 实例的话,特别是在一些基于 promise 的异步库比如 axios 等一定要小心,因为你不知道什么时候这些异步请求会抛出异常而你并没有处理它,所以最好添加一个 Promise 全局异常捕获事件 unhandledrejection

window.addEventListener("unhandledrejection", e => {
 console.log('unhandledrejection',e)
});

vue工程异常

window.onerror并不能捕获.vue文件发生的获取,Vue 2.2.0以上的版本中增加了一个errorHandle,使用Vue.config.errorHandler这样的Vue全局配置,可以在Vue指定组件的渲染和观察期间未捕获错误的处理函数。这个处理函数被调用时,可获取错误信息和Vue 实例。

//main.js
import { createApp } from "vue";
import App from "./App.vue";

let app = createApp(App);
app.config.errorHandler = function(e) {
  console.log(e);
  //错误上报...
};
app.mount("#app");
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值