騰訊雲技術社群-掘金主頁持續為大家呈現雲端計算技術文章,歡迎大家關注!
作者:vienwu
javascript的出錯我們應該都很熟悉,例如xxx undefined
,SyntaxError
等。
我們team將出現錯誤的javascript程式碼取名為badjs,也有一個開源的badjs專案,用於捕獲和分析js錯誤,並提供了一些基礎的報表資料分析。
捕獲錯誤一般有兩種方式:
- 使用window.onerror()捕獲全域性的js錯誤資訊
- 使用
try{...}catch(e){...}
包裹需要執行的程式碼,獲取error物件的屬性定位錯誤並上報
第一種方式最簡單,但當執行的js程式碼和我們的站點在不同域即跨域時,由於瀏覽器的安全限制,onerror()方法只能捕獲到一個固定的錯誤程式碼Script error.
。
具體可參考這裡:點選檢視
我們團隊目前的業務基本都會將靜態資源部署到cdn伺服器,和站點處於不同域,所以需要解決跨域問題。
跨域問題可以通過伺服器端設定access-control-allow-orgin:*
解決,但並不完美。這個問題更深入的資訊可以參考這裡:github.com/BetterJS/ba…
第二種方式是手動包裹一些要檢測的程式碼,沒有跨域問題並且可以獲取到err的物件的詳細出錯資訊。
這種方式相對麻煩一些,但可以通過全域性的hook,處理大部分情況,免除每次手動寫try...catch的煩惱。
我們都知道js程式碼的執行是通過事件和定時器觸發執行的,所以理論上將事件觸發時的回撥、定時器的回撥包裹即可。
我們的badjs專案主要是通過第二種方式實現,並根據現有的業務,對以下幾種方法進行了處理:
define()
,require()
等方法- jQuery封裝的一些事件,如
$.event.add
,$.event.remove
,ajax等 - setTimeout setInterval等
這裡處理的原理比較簡單,類似下面的程式碼:
function define(){
...
}
var a = define;
define = function(){
try{
a.apply(this,arguments);
}catch(e){
...錯誤上報
}
};複製程式碼
這裡還有一些相容性的問題需要處理,例如在ie低版本中setTimtout和setInterval方法並不是function
型別,而是object
,所以無法使用改寫function
的方式進行包裹。類似的還有document.attachEvent
方法也是object
,不是function
。
除了對以上方法的單獨處理外,還有一些意外情況無法處理,例如:
- window.onload,Image.prototype.onerror等瀏覽器和dom的事件,這類方法無法直接改寫function
- 第三方的外掛的自定義事件,如flash播放器提供的一些用於播放控制的事件。
- 新的一些api,如FileReader.prototype.onload等
這些意外情況很難做全域性的hook,所以只好手動try...catch。
我們的badjs也提供了一個便捷的api,例如原始碼是這樣:
var img = new Image();
img.onload = function(){
...
};複製程式碼
使用tryjs包裹
var img = new Image();
img.onload = tryJs.spyCustom(function(){
...
});複製程式碼
除此之外,try...catch能獲取的err物件在各不同的瀏覽器之間,也有一些差異。好在有人已經做一個頁面展示詳細的差異,參考url: broofa.com/tests/Error…
一些其他的補充
回到捕獲js錯誤這件事本身,是為了更好的監控並定位錯誤,幫助我們改善程式碼質量,所以kael也提到另外一個思路,可以灰度一部分使用者,直接使用主域而不是cdn的js,直接避免跨域問題
,這個思路也值得一試。
另外,錯誤上報資料和訪問量等資料如果到結合一起分析,不僅可以更快速的定位問題,甚至可以實現監控自動告警等,當然這個也非常複雜。
相關推薦
移動端tryjs異常捕獲
新使用者850元大禮包,輕鬆上雲
玩轉JavaScript正規表示式
此文已由作者授權騰訊雲技術社群釋出,轉載請註明文章出處
原文連結:www.qcloud.com/community/a…
獲取更多騰訊海量技術實踐乾貨,歡迎大家前往騰訊雲技術社群