為什麼要做前端錯誤監控? 1. 為了保證產品的質量 2. 有些問題只存在於線上特定的環境 3. 後端錯誤有監控,前端錯誤沒有監控 前端錯誤的分類 前端錯誤分為兩類: 即時運行錯誤和資源載入錯誤 即使運行錯誤的捕獲方式 即時運行錯誤的捕獲方式分為兩類 try...catch 通過try...catch ...
為什麼要做前端錯誤監控?
1. 為了保證產品的質量
2. 有些問題只存在於線上特定的環境
3. 後端錯誤有監控,前端錯誤沒有監控
前端錯誤的分類
前端錯誤分為兩類: 即時運行錯誤和資源載入錯誤
即使運行錯誤的捕獲方式
即時運行錯誤的捕獲方式分為兩類
- try...catch
- window.onerror
try...catch
通過try...catch我們能夠知道出錯的信息,並且也有堆棧信息可以知道在哪個文件第幾行第幾列發生錯誤
try { // 代碼段 } catch (err) { console.log(err.message) }
缺點:
- 沒法捕捉try,catch塊,當前代碼塊有語法錯誤,JS解釋器壓根都不會執行當前這個代碼塊,所以也就沒辦法被catch住;
- 沒法捕捉到全局的錯誤事件,也即是只有try,catch的塊裡邊運行出錯才會被你捕捉到,這裡的塊你要理解成一個函數塊
關於第一個缺點,我們沒有任何解決辦法,但是一般語法階段我們是能在開發階段/或者用工具檢測到的,於是乎它就被忽略了
第二個缺點應該怎麼理解呢? try...catch只能捕捉到當前執行流裡邊的運行錯誤,對於非同步回調來說,是不屬於這個try...catch塊的
window.onerror
全局捕獲。window.onerror一樣可以拿到出錯的信息以及文件名、行號、列號等信息,還可以在window.onerror最後return true讓瀏覽器不輸出錯誤信息到控制台
/* * @param msg{String}:錯誤消息 * @param url{String}:引發錯誤的腳本的URL * @param line{Number}:發生錯誤的代碼行 * @param colunm{Number}:發生錯誤的代碼列 * @param error{object}:錯誤對象 */ window.onerror = function (msg, url, line, colunm, error) { // 返回 true 則錯誤消息不顯示在控制台,返回 false,則錯誤消息將會展示在控制台 return true; }
最後window.onerror的實現方法
window.onerror = function (msg, url, line, col, error) { //沒有URL不上報!上報也不知道錯誤 if (msg != "Script error." && !url) { return true; } setTimeout(function () { var data = {}; //不一定所有瀏覽器都支持col參數 col = col || (window.event && window.event.errorCharacter) || 0; data.url = url; data.line = line; data.col = col; if (!!error && !!error.stack) { //如果瀏覽器有堆棧信息 //直接使用 data.msg = error.stack.toString(); } else if (!!arguments.callee) { //嘗試通過callee拿堆棧信息 var ext = []; var f = arguments.callee.caller, c = 3; //這裡只拿三層堆棧信息 while (f && (--c > 0)) { ext.push(f.toString()); if (f === f.caller) { break; //如果有環 } f = f.caller; } ext = ext.join(","); data.msg = ext; } //把data上報到後臺! console.log(data) }, 0); return true; };
資源載入錯誤
object.onerror
img、script標簽都可以添加onerror事件,當資源請求失敗的時候,都會觸發該事件
var img = document.getElementById('img'); img.onerror=function(){ console.log("出錯啦"); }
performance.getEntries()
performance是h5的新特性之一,使用該方法能獲取到當前頁面已經載入到的資源,返回的是一個數組對象。下麵給出一個例子
獲取頁面中沒有成功載入的圖片資源?
步驟一:通過performance.getEntries()獲取已經載入了的圖片資源
let arr = [], reg = (/\.jpg$|\.jpeg$|.png$|\.gif$/i); performance.getEntries().forEach(item => { if (reg.test(item.name)) { arr.push(item.name) } })
步驟二:獲取頁面中所有的img標簽
let imgList=document.getElementByTagname('img')
步驟三:利用獲取到的img的長度減去已經載入到的長度,如果大於0的部分,就是載入失敗的
let arr = [], imgList=null, num=0, reg = (/\.jpg$|\.jpeg$|.png$|\.gif$/i); performance.getEntries().forEach(item => { if (reg.test(item.name)) { arr.push(item.name) } }) imgList=document.getElementsByTagName('img'); num=imgList.length-arr.length;
Error事件捕獲
資源載入錯誤,雖然會阻止冒泡,但是不會阻止捕獲。true:捕獲,false:冒泡
// window.addEventListener第三個參數是true的時候是捕獲的過程,false是冒泡的過程 window.addEventListener('error',function(e){ console.log("捕獲",e) },true)
跨域的JS文件異常捕獲
為了提升web性能,大部分web產品都有CDN部署,將資源部署到不同的功能變數名稱上,但是我們都知道瀏覽器是有同源策略的,當載入不同功能變數名稱的腳本發生錯誤時,語法錯誤的細節不會報告,僅返回"Script error",針對這種問題,可以在伺服器上設置"Access-Control-Allow-Origin:*",在請求資源的script標簽上加上crossorigin屬性即可
<script src="xxxx/js/store.js" crossorigin></script>