我已淪為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的同學立馬就懂了,不解釋;