web前端:处理 JavaScript 异常的一个想法

    作者:sofish 更新于: 2020-12-07 12:53:54

    Web开发

      Javascript一种直译式脚本语言,是一种动态类型、弱类型、基于原型的语言,内置支持类型。它的解释器被称为JavaScript引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在HTML(标准通用标记语言下的一个应用)网页上使用,用来给HTML网页增加动态功能。

      可能由于网络、浏览器问题、缓存等原因,可能导致线上执行js的时候与开发环境并不一样,会抛出异常。js异常基本上是前端开发工程师的家常便饭。如何记录,并使用它,却很少人关注。最近在考虑一个想法,基本上涉及到两步:收集和使用。

      一、收集

      对于error收集这一块,还是比较方便的,因为在各浏览器中都有一个接口:window.onerror:

      window.onerror=function(errorMessage,scriptURL,lineNumber){

      alert(errorMessage,scriptURL,lineNumber)

      }

      甚至中提供了StackTrace,比如在try/catch中还提供了e.stack(各个浏览器不同,可以使用eriwen/javascript-stacktrace这个兼容库),试一下下面这段代码:

      try{

      fn()

      }catch(e){

      alert(e.stack)

      }

      所以收集这些错误还是比较方便的,这里需要注意的事,使用window.addEventListener('error',callback,isBubble)中callback的第一个参数并不是event,而是一个Errorobject。这样的话,为了方便,使用window.onerror是一个不错的选择,但通过dot操作符监听的事件是可以重载的,并且这段监听脚本理论上是放在所有js最前面的,所以需要考虑其中的风险。

      二、使用

      之前在支付宝的时候,线上js报错会变成一个邮件,发给前端开发team,每个人自己认领、解决。其实这是一个不错的选择,也解决了最基本的问题:立即响应,修掉。不过也存在着一个问题,如果避免同样的错误?我的初步想法是这样的:

      以URL为单元,记录同一个页面的报错:方便统一解决

      记录错误包括:PageURL,UserAgent,ScriptURL,ErrorMessage和LineNumber

      每个错误解决后,都可以在一个地方写解决方案,看到的人可以评论、加分,最终会存档起来,作为一个知识库,并用有方便的api可以使用这些知识库的内容

      在开发的时候,相同页面window.onerror的时候,通过插件,分析ErrorMessage识别出类型,加上URL的判断,给予开发者提醒前人犯过的错误

      开发者可以订阅知识库上某些标签,自动接收邮件(当然也可以根据文件注释、mapping等方式做更好的配对)

      为什么这样做?主要是为了解决下面的一些问题:

      形成知识库,开发者可以从中得到学习,特别是新人

      工具保证效率的提升和避免重复错误重复解决

      订阅保证通知更具针对性

      三、注意点

      1.收集的时候使用POST发送

      有时候ErrorMessage可能会比较长,而浏览器的URL长度是有限制的,如果存的错误不多的话,可以考虑用GET发送,但通常来说POST可以把所有数据都发送到后台。

      2.何时发送数据

      建议在触发onerror的时候发送。在第一次有这个想法的时候,尝试着在onbeforeonload的时候发送,但POST请求还没open就已经被浏览器中断了。

      3.存于数据库以哪个作为索引比较好?

      通常来说以URL可能会比较适合多数网站。但像百姓网、淘宝等UGC比较多的网站,可能需要变通一下以记录URL。毕竟不同帖子不同URL都是同一套代码。

      那以Error作为索引呢?其实无论是那种,看自己需求选择吧。

      4.是否记录所有错误

      这个也比较合适根据需求来看。百姓网有各种乱七八糟的报错可能都是来自到baidu/Google的ad外链。

      四、结语

      目前初步实现了一个收集的工具(sofish/stacktrace.js)和存储方式(以URL为索引),是否继续,还需要时间和进一步考虑,先发出来,抛砖引玉。

      五、附录

      php

      $url=newUrl();

      $page=$url->post('page');

      if(!$page)return;

      classErrorTraceextendsMongoData{

      //MongoData中没有,区别http://stackoverflow.com/a/7958954

      publicfunctionfindOne($obj){

      return$this->connection->findOne($obj);

      }

      };

      $store=newErrorTrace();

      $fields=array(

      'url'=>$url->post('url'),

      'message'=>$url->post('message'),

      'line'=>$url->post('line'),

      'ua'=>$url->post('ua'),

      );

      $index=array('page'=>$page);

      $hash=md5(json_encode($fields));

      //不重复记录一个错误,所有错误记录在同一个URL下

      if($field=$store->findOne($index)){

      if(isset($field[$hash]))return;

      return$store->setAttr(newQuery('page',$page),$hash,$fields);

      }

      $store->page=$page;

      $store->$hash=$fields;

      $store->save();

      ?>

      ThisGistbroughttoyoubyGitHub.

      在1995年时,由Netscape公司的BrendanEich,在网景导航者浏览器上首次设计实现而成。因为Netscape与Sun合作,Netscape管理层希望它外观看起来像java,因此取名为JavaScript。但实际上它的语法风格与Self及Scheme较为接近。

      为了取得技术优势,微软推出了JScript,CEnvi推出ScriptEase,与JavaScript同样可在浏览器上运行。为了统一规格,因为JavaScript兼容于ECMA标准,因此也称为ECMAScript。

课课家教育

未登录