首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
华为云
V2EX  ›  程序员

前端异常 — 跨终端实时追踪

  •  
  •   famanoder · 2016-12-08 21:21:49 +08:00 · 1667 次点击
    这是一个创建于 683 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我已沦为 IE 狗!!!

    从 9 月份一开始,新项目正式启动,产品以客户端的形式发布,目前用的是.NET 的 WebBrowser 内嵌网页的形式开发,对于后端来说,一切都是那么自然、简单;可对于前端来说,彻底将我带入到了 IE 的黑洞,自此万劫不复!说实话,我内心无比鄙视这个 WebBrowser ,因为 windows 绑定了 IE , WebBrowser 默认使用 IE 内核,按理说现在 win7 及以上系统居多,所以这个内核怎么也是 IE9+居多才对啊,可恶的是,众多系统都是重装的非正版阉割后的系统,可恶的是, WebBrowser 在这些系统哪怕是装的 win7 、 IE11 都调的是 IE7 ,可恶的是程序对其不可控!可恶的是这个调用的 IE7 与浏览器的 IE7 还不太一样,我叫它非 7 非 8 ,有时我在 IE7 浏览器里看到一个样子,到了黑壳子里弹出检测结果是 IE7 ,样子居然和浏览器上不一样,完全(想骂人。。。)不在套路上!而且没有控制台,任意一个异常,无论是否影响程序,都会弹出一个讨人厌的脚本错误的提示框!由于我在浏览器上调试和开发的,所以一开始并不知道会有这些问题,即便当时我兼容到了 IE7 ,到了壳子里面又是一番乌七八糟的问题!当时每天下班回家躺在床上,我都在怀疑自己的前端之路是不是走进了一条死胡同,完全看不到光,说好的炫酷呢,说好的大前端呢?尼玛这都什么鬼?

    欣慰的是后端同学在积极研究怎么切换到 webkit 的壳子,基于一些不可预知的问题,以及项目催的太紧,到目前为止,我依然天天面对着 IE7891011 。。。。。不要拦我。。。让我哭会儿。。。

    话说还是要做个坚强的孩子!自己选择的路,再苦再累也要咬牙走完呀;一方面,兼容问题是前端不可避免的问题;另一方面,既然眼下没有更好的方案,只有靠自己一步步走稳脚下的路了;

    皇天不负苦心人,终于让我磨出了一个 ErrorInspector 模块!

    基于以上可恶的让人怀疑人生的问题,首先解决以下问题:

    1 、兼容到 IE7 ;

    2 、异常的反馈与追踪(支持跨域);

    3 、屏蔽掉那个讨人厌的脚本错误提示框;

    4 、要跨终端,比如那个丑的不要的 IE 壳子,不可调试;

    5 、错误实时上报并通知和展示;

    6 、一并追踪与后端交互的错误,比如: 500 、 404 ,把 Jquery 的 ajax 拉进来;

    7 、包装 try_catch ,多用 try_catch ;

    由于要兼容到 IE7 ,那么基础库用 Jquery 肯定最好了,加上自己平时造的一些模块和组件以及 Jquery 的插件,基本够开发用了;可怜的我再次与牛逼的 React 、 Angular 擦肩而过了;现在以 Nodejs 的模块化方式开发,用 webpack 打包合并,目前感觉还凑合;

    最初的想法是,通过 window.onerror 和 try_catch 捕获并上报错误到一个独立的错误收集站点,不需要后端配合,自己用 Express 造一个简单的站点就是,通过 H5 的 webSocket 和 Node 的 Socket.io 实时响应上报的错误,如果已打开浏览器端无需刷新即可收到通知,或者直接发送邮件提示,达到跨终端实时追踪上报;如果可以的话,在 Web 上可以做更多工作,比如,图形化分析和展示,常见错误的解决方法的预测和提示,如果是线上收集站点还可以对错误极其解决方法做分类收集,供浏览者参考;总之, face to error,just do it !

    因为问题最终上报到我这,所以就不存在浏览器兼容问题了,当然选最好的谷歌了, BSIE !!!;没做太多优化,第一版错误反馈展示的页面大概是这个傻样子:

    图片描述

    当然,图片里是测试的结果,每条展开有更多错误的详情,包括错误引发的文件地址、行号、错误类型、浏览器版本、时间、所在页面、触发节点等;实际发现, window.onerror 捕获的错误并不总是很详细,最好是多用包装好的 try_catch 去主动上报,才会比较容易定位错误源,多用 try_catch 是个好习惯;因为难免存在跨域的问题,默认使用 new Image 的方式 GET 数据,当然,这不是必须的,支持自定义上报地址和上报方法;至于屏蔽掉那个讨人厌的脚本错误提示框,其实很简单,在 window.onerror 最后 return true 就是的,但是在谷歌里就会屏蔽掉控制台输出的内容,最好在线上环境使用,毕竟本地开发还得在控制台里调试;

    由于 Jquery 的 Ajax 使用特别灵活,所以做好全局去捕获 Ajax 与后端交互的错误;看看 Jquery 的 Ajax 常见用法:

    // 以 GET 为例
    
    $.ajax({
    	url:'',
    	success:function(data){},
    	error:function(){}
    });
    $.get(url,data,function(data){});
    $.get(url,data).success(function(data){}).error(function(){});
    $.get(url,data).then(function(data){},function(err){});
    
    // ...
    

    这么多种用法,每次都去捕获 error 事件,然后在里面上报,肯定是相当不靠谱的; Jquery 是很好用的,可以通过设置全局的 error 事件来捕获上面各种方式下的错误,爽不爽?比如这样:

    $.ajaxSetup({
        timeout:setAjax.$.timeout,
        error: function(xhr){
            setTimeout(function () {
                util.getArgType(setAjax.$.onError)=='function'?setAjax.$.onError(xhr):alert(xhr.status+','+xhr.statusText);
            }, 1);					
        }
    });
    

    不过这种错误一般后端的可能性大些,前端常见的就是这里的参数没传好,引发的后端错误,当然可以选择屏蔽不上报,或简单的提示个服务器异常就行了;

    ErrorInspector 的用法:

    1 、最好放在各大 library 的后面,你写的 JS 前面,因为框架本身一般不会引发错误,主要是监控自己写的代码可能存在的未预知的异常;

    2 、初始化配置:

    ErrorInspector.Config={
    	url:'http://localhost:2333/ErrorInspector/xiaofeng',   //上报地址
    	qs:{
    		id:location.host,            //默认以当前域为 id
    		page:location.host+location.pathname,//错误页面地址
    		from:Url,                    //错误来源的地址
    		row:Number,                  //错误行号
    		col:Number,                  //错误列号
    		msg:String,                  //错误详情
    		browser:util.Browser,        //浏览器类型及版本,默认几大主流浏览器,后续完善
    		time:util.fmtTime(),         //错误触发的时间
    		inspector:String,            //上报者 window|user|log......
    		// ...其他参数
    		ext:'hufeng'                 //扩展的参数
    	},
    	$:{
    		timeout:Number,              //Jquery 的 Ajax 超时设置,会触发 onError
    		onError:function(xhr){}      //全局的 Jquery 的 Ajax 错误捕获
    	},
            submit:function(data){},         //自定义上报方式,回调了上报内容     
    	IgnoreFromJSPattern:/reg/ig,     //屏蔽错误来源的地址,比如第三方的广告
    	IgnoreMsgPattern:/reg/ig,        //屏蔽上报的消息内容,比如没太大意义的 script.error
    	IgnoreBrowserError:0|1           //是否屏蔽控制台,主要屏蔽掉那个 IE 上讨厌的弹框
    }
    

    ErrorInspector.Config.qs 里的参数一般无需过问,错误触发时会自己收集上报;

    3 、 Tryit(function(report,log){});

    包装好的 try_catch ,回调的 ErrorInspector.report 和 ErrorInspector.log 其实大同小异,除了 try_catch 里的上报外,可以用回调值继续自定义上报;一般用这个函数包装代码块;

    4 、 ErrorInspector.report({name:value});

    主动上报;

    5 、 ErrorInspector.log;

    模拟简单的 console.log ,其实更像 alert ,可以充当统计代码用,或许还需改进;

    6 、后端使用 Express 和 Socket.io ,玩过 H5 的 webSocket 的同学立马就懂了,不解释;

    这些天被 IE 忙活坏了,例子未整理,唉,其实 IE 并非那么可怕! ErrorInspector.js 仅作分享,能力有限,欢迎改进! github 地址: https://github.com/famanoder/face2error/blob/master/public/ErrorInspector.js

    如果你已在路上,就勇敢的向前吧!

    原文来自:http://famanoder.com/bokes/5839e76bd37f5e680891fb47

    11 回复  |  直到 2016-12-09 17:35:51 +08:00
        1
    mingyun   2016-12-08 23:17:29 +08:00
    厉害了
        2
    Rice   2016-12-09 08:53:42 +08:00
    终端报错能实时追踪啊,这个不错
        3
    Rice   2016-12-09 08:54:19 +08:00
    感觉这个非常有用啊。
        4
    Clarencep   2016-12-09 09:03:26 +08:00
    哎,心疼 LZ...

    咋不一上来就用 eletron 呢
        5
    hiro0729   2016-12-09 09:51:21 +08:00
    node-webkit , nwjs , Electron ,选择这么多,偏偏要自虐进 ie 的坑。。。
        6
    gongbaodd   2016-12-09 09:56:49 +08:00
    判断不到那么精确吧, js 都是经过压缩过的
        7
    xieyu33333   2016-12-09 10:13:43 +08:00
    你应该使用 sentry
        8
    wangxkww   2016-12-09 14:52:35 +08:00
    这时候不应该上 https://github.com/cefsharp/CefSharp 么……
        9
    famanoder   2016-12-09 17:33:49 +08:00
    @wangxkww 后端在研究中
        10
    famanoder   2016-12-09 17:35:08 +08:00
    @gongbaodd 所以一般 Tryit 或 report 主动上报
        11
    famanoder   2016-12-09 17:35:51 +08:00
    @hiro0729 后端是.NET ,我做不了主啊
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   3291 人在线   最高记录 3762   ·  
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.1 · 39ms · UTC 01:32 · PVG 09:32 · LAX 18:32 · JFK 21:32
    ♥ Do have faith in what you're doing.
    沪ICP备16043287号-1