前端js錯(cuò)誤監(jiān)控系列一:js不同異常類型的捕獲

一、js異常的捕獲

1.window.onerror

當(dāng)javascript運(yùn)行發(fā)生錯(cuò)誤時(shí),window會(huì)觸發(fā)一個(gè)ErrorEvent接口的error事件,并執(zhí)行window.onerror()。這是記錄客戶端錯(cuò)誤并將其報(bào)告給服務(wù)器的最簡(jiǎn)單方法之一。

window.onerror = function(message, source, lineno, colno, error) { ... }
函數(shù)參數(shù):

  • message:錯(cuò)誤信息(字符串)??捎糜贖TML onerror=""處理程序中的event。
  • source:發(fā)生錯(cuò)誤的腳本URL(字符串)
  • lineno:發(fā)生錯(cuò)誤的行號(hào)(數(shù)字)
  • colno:發(fā)生錯(cuò)誤的列號(hào)(數(shù)字)
  • errorError對(duì)象(對(duì)象)

window.onerror含有詳細(xì)的error堆棧信息,存在error.stack中。遺憾的是stack屬性是非標(biāo)準(zhǔn)的,并且其實(shí)現(xiàn)在不同的瀏覽器中也有所不同。幸運(yùn)的是,有一些工具可以標(biāo)準(zhǔn)化堆棧屬性,以便在瀏覽器之間保持一致。例如,raven-js使用TraceKit標(biāo)準(zhǔn)化錯(cuò)誤字符串

onerror.png

上圖為不同瀏覽器對(duì)各個(gè)參數(shù)的支持,某些瀏覽器沒(méi)有錯(cuò)誤對(duì)象,就沒(méi)有堆棧跟蹤屬性。這意味著這些瀏覽器無(wú)法從onerror捕獲的錯(cuò)誤中檢索有價(jià)值的堆棧信息。默認(rèn)情況下,Raven.js(Sentry的JavaScript SDK)會(huì)謹(jǐn)慎地使用內(nèi)置方法來(lái)嘗試自動(dòng)將代碼包裝在try / catch塊中。這樣做是為了嘗試捕獲所有腳本中的錯(cuò)誤消息和堆棧跟蹤信息,而不管它們來(lái)自何處。

2.script error的解決方式

另外,需要注意的是當(dāng)加載自非同源的腳本中發(fā)生語(yǔ)法錯(cuò)誤時(shí),為避免信息泄露,語(yǔ)法錯(cuò)誤的細(xì)節(jié)將不會(huì)報(bào)告,而代之簡(jiǎn)單的**"Script error."**。這是瀏覽器所做的安全限制措施
解決方案1:
添加 crossorigin="anonymous" 屬性。
添加跨域 HTTP 響應(yīng)頭:Access-Control-Allow-Origin: *
完成上述兩步之后,即可通過(guò) window.onerror 捕獲跨域腳本的報(bào)錯(cuò)信息。
解決方案2:
難以在 HTTP 請(qǐng)求響應(yīng)頭中添加跨域?qū)傩詴r(shí),還可以考慮 try catch 這個(gè)備選方案??梢栽?catch 語(yǔ)句中手動(dòng)上報(bào)捕獲的異常。如果你使用sentry的raven.js的話,你會(huì)發(fā)現(xiàn)你什么都不用做,他依然可以幫你捕獲到一些錯(cuò)誤的非常具體信息,關(guān)鍵就是raven源碼中的install方法中調(diào)用的_instrumentTryCatch函數(shù)起了作用,他通過(guò)tryCatch的方式wrap了一些關(guān)鍵函數(shù),使得這些函數(shù)里的報(bào)錯(cuò)能夠捕獲

3.資源加載錯(cuò)誤的捕獲

當(dāng)一項(xiàng)資源(如<img><script>加載失敗,加載資源的元素會(huì)觸發(fā)一個(gè)[Event]接口的事件,并執(zhí)行該元素上的onerror()處理函數(shù)。這些error事件不會(huì)向上冒泡到window,不過(guò)能被window.addEventListener在捕獲階段捕獲。

window.addEventListener('error', event => (){ 
  // 處理錯(cuò)誤信息
}, true);
// true代表在捕獲階段調(diào)用,false代表在冒泡階段捕獲。

但這里需要注意,使用window.onerror和window.addEventListener('error')都能捕獲運(yùn)行錯(cuò)誤,但是window.onerror含有詳細(xì)的error堆棧信息,存在error.stack中,所以我們選擇使用onerror的方式對(duì)js運(yùn)行時(shí)錯(cuò)誤進(jìn)行捕獲。因此對(duì)addEventListener綁定的事件需要過(guò)濾避免重復(fù)上報(bào),判斷為資源錯(cuò)誤的時(shí)候才進(jìn)行上報(bào)。

4.未處理的promise錯(cuò)誤

當(dāng)promise被reject并且錯(cuò)誤信息沒(méi)有被處理的時(shí)候,會(huì)拋出一個(gè)unhandledrejection

這個(gè)錯(cuò)誤不會(huì)被window.onerror以及window.addEventListener('error')捕獲,但是有專門的window.addEventListener('unhandledrejection')方法進(jìn)行捕獲處理。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容