JS前端錯誤監(jiān)控捕獲以及上報方法詳解
前端錯誤捕獲方法
前端捕獲錯誤的方法:
try..catch:捕獲的異常必須是線程執(zhí)行進入到try...catch且try...catch未執(zhí)行完的時候拋出來。
語法異常在語法檢查階段就報錯了,線程尚未進入try...catch代碼塊,所以無法捕獲到異常。
try { a. }catch(e) { console.log('catch error:', e) }
不能捕獲setTimeout或者Promise中的錯誤。以下錯誤都不能捕獲。如果想捕獲,要將try...catch放入到異步代碼內(nèi)部。
try { new Promise((res, rej) => { rej('promise reject error') // throw new Error('promise throw error') }) } catch (e) { console.log('catch error:', e) } ? ? try { setTimeout(() => { throw new Error('setTimeout throw error') }, 0) } catch (e) { console.log('catch error:', e) }
能捕獲async 異常
async function fn() { try { let res = await new Promise((res, rej) => { // rej('my reject err') // unhandledrejection 可以處理 throw Error('my throw error') // unhandledrejection 可以處理 }) } catch (err) { console.log('catch err', err) } } ? fn()
window.onerror:當(dāng)資源加載失敗或無法使用時,會在Window對象觸發(fā)error
事件,無法捕獲promise錯誤,可以捕獲setTimeout錯誤。
當(dāng)加載自不同域的腳本中發(fā)生語法錯誤時,瀏覽器為避免信息泄露的安全風(fēng)險,語法錯誤的細節(jié)將不會報告給瀏覽器console中,而是使用"Script error."信息代替。解決辦法是為 script 標(biāo)簽添加 crossOrigin 屬性,并且服務(wù)端配置Access-Control-Alow-Origin:*
unhandledrejection:當(dāng) Promise 被 reject 且沒有 reject 處理器的時候,會觸發(fā) unhandledrejection
事件
不同場景錯誤處理方式
總結(jié)先行: addEventListener('error') + addEventListener('unhandledrejection') 的方式恰好能夠覆蓋5種異常錯誤(同步任務(wù),普通異步任務(wù),promise任務(wù),async任務(wù),資源加載)的捕獲。
可以將unhandledrejection捕獲到的錯誤throw出來讓error進行捕獲之后統(tǒng)一上報。
- 跨域資源加載問題:window.addEventListener('error',()=>{}),并且script 標(biāo)簽添加 crossOrigin 屬性,并且服務(wù)端配置
Access-Control-Alow-Origin
- 定時器內(nèi)部函數(shù)拋出錯誤:window.onerror或者window.addEventListener('error',()=>{})
- 靜態(tài)資源加載的異常:window.addEventListener('error')可以捕獲,但是window.onerror不能捕獲
- 網(wǎng)絡(luò)請求的異常:axios的響應(yīng)攔截器
- 線上壓縮代碼:開啟sourceMap
promise:常常配置catchhandler進行處理,沒有處理的rejected的promise通過unhandledrejection
// 能觸發(fā) unhandledrejection ,因為未顯式處理reason Promise.reject('error').then() Promise.reject('error').then(console.log) ? // 不能觸發(fā) unhandledrejection ,因為已處理reason Promise.reject('error').then(console.log, console.log) // 不能觸發(fā) unhandledrejection ,因為沒處理reason,直接拋出異常 Promise.reject('error')
React捕獲錯誤:錯誤邊界(Error Boundaries)
部分 UI 的 JavaScript 錯誤不應(yīng)該導(dǎo)致整個應(yīng)用崩潰,錯誤邊界是一種 React 組件,這種組件可以捕獲發(fā)生在其子組件樹任何位置的 JavaScript 錯誤,并打印這些錯誤,同時展示降級 UI,而并不會渲染那些發(fā)生崩潰的子組件樹。錯誤邊界可以捕獲發(fā)生在整個子組件樹的渲染期間、生命周期方法以及構(gòu)造函數(shù)中的錯誤。
錯誤邊界無法捕獲以下場景中產(chǎn)生的錯誤:
- 事件處理(了解更多)
- 異步代碼(例如
setTimeout
或requestAnimationFrame
回調(diào)函數(shù)) - 服務(wù)端渲染
- 它自身拋出來的錯誤(并非它的子組件)
Vue捕獲錯誤:
全局-Vue.config.errorHandler:指定組件的渲染和觀察期間未捕獲錯誤的處理函數(shù)。這個處理函數(shù)被調(diào)用時,可獲取錯誤信息和 Vue 實例。
- 從 2.2.0 起,這個鉤子也會捕獲組件生命周期鉤子里的錯誤。同樣的,當(dāng)這個鉤子是
undefined
時,被捕獲的錯誤會通過console.error
輸出而避免應(yīng)用崩潰。 - 從 2.4.0 起,這個鉤子也會捕獲 Vue 自定義事件處理函數(shù)內(nèi)部的錯誤了。
- 從 2.6.0 起,這個鉤子也會捕獲
v-on
DOM 監(jiān)聽器內(nèi)部拋出的錯誤。另外,如果任何被覆蓋的鉤子或處理函數(shù)返回一個 Promise 鏈 (例如 async 函數(shù)),則來自其 Promise 鏈的錯誤也會被處理。 - 錯誤追蹤服務(wù) Sentry 和 Bugsnag 都通過此選項提供了官方支持。
生命周期鉤子-errorCaptured:在捕獲一個來自后代組件的錯誤時被調(diào)用。此鉤子會收到三個參數(shù):錯誤對象、發(fā)生錯誤的組件實例以及一個包含錯誤來源信息的字符串。此鉤子可以返回 false
以阻止該錯誤繼續(xù)向上傳
傳播規(guī)則:
- 默認情況下,如果全局的
config.errorHandler
被定義,所有的錯誤仍會發(fā)送它,因此這些錯誤仍然會向單一的分析服務(wù)的地方進行匯報。 - 如果一個組件的 inheritance chain (繼承鏈)或 parent chain (父鏈)中存在多個
errorCaptured
鉤子,則它們將會被相同的錯誤逐個喚起。 - 如果此
errorCaptured
鉤子自身拋出了一個錯誤,則這個新錯誤和原本被捕獲的錯誤都會發(fā)送給全局的config.errorHandler
。 - 一個
errorCaptured
鉤子能夠返回false
以阻止錯誤繼續(xù)向上傳播。本質(zhì)上是說“這個錯誤已經(jīng)被搞定了且應(yīng)該被忽略”。它會阻止其它任何會被這個錯誤喚起的errorCaptured
鉤子和全局的config.errorHandler
。
錯誤信息上報
捕獲到錯誤信息后進行上報,對于前端監(jiān)控很重要。
上報的方式有三種:
ajax進行上報
發(fā)現(xiàn)錯誤的時候上傳錯誤到接口進行存儲。
但是存在一些問題:
- 有嚴格的跨域限制
- 上報請求可能會阻塞業(yè)務(wù)
- 請求容易丟失(被瀏覽器強制cancel)
image上報
由于圖片天然可跨域,又能兼容所有的瀏覽器,而js和css等其他資源文件則可能出現(xiàn)安全攔截和跨域加載問題。
let img = new Image() img.src='請求的url'
但由于是一個get請求,上報的數(shù)據(jù)量在不同的瀏覽器下上限不一致(2kb-8kb),這就可能出現(xiàn)超出長度限制而無法上報完整數(shù)據(jù)的情況。因此,圖片上報也是一個“不安全”的方式。
sendBeacon
navigator.sendBeacon()
方法可用于通過 HTTP POST 將少量數(shù)據(jù) 異步 傳輸?shù)?Web 服務(wù)器。
它主要用于將統(tǒng)計數(shù)據(jù)發(fā)送到 Web 服務(wù)器,同時避免了用傳統(tǒng)技術(shù)
這個方法主要用于滿足統(tǒng)計和診斷代碼的需要,這些代碼通常嘗試在卸載(unload)文檔之前向 Web 服務(wù)器發(fā)送數(shù)據(jù)。過早的發(fā)送數(shù)據(jù)可能導(dǎo)致錯過收集數(shù)據(jù)的機會。然而,對于開發(fā)者來說保證在文檔卸載期間發(fā)送數(shù)據(jù)一直是一個困難。因為用戶代理通常會忽略在 unload 事件處理器中產(chǎn)生的異步 XMLHttpRequest。
navigator.sendBeacon(url, data);
使用 sendBeacon()
方法會使用戶代理在有機會時異步地向服務(wù)器發(fā)送數(shù)據(jù),同時不會延遲頁面的卸載或影響下一導(dǎo)航的載入性能,這意味著:
- 數(shù)據(jù)發(fā)送是可靠的。
- 數(shù)據(jù)異步傳輸。
- 不影響下一導(dǎo)航的載入。
以上就是JS前端錯誤監(jiān)控捕獲以及上報方法詳解的詳細內(nèi)容,更多關(guān)于JS前端錯誤監(jiān)控捕獲上報的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JavaScript設(shè)計模式之原型模式和適配器模式示例詳解
這篇文章主要為大家介紹了JavaScript 原型模式和適配器模式示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-08-08JS前端可視化canvas動畫原理及其推導(dǎo)實現(xiàn)
這篇文章主要為大家介紹了JS前端可視化canvas動畫原理及其推導(dǎo)實現(xiàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-08-08JavaScript中document.activeELement焦點元素介紹
這篇文章主要給大家分享 JavaScript中document.activeELement焦點元素介紹,下面文章圍繞了document.activeElement屬性展開詳細內(nèi)容,需要的朋友可以參考一下,希望對大家有所幫助2021-11-11JQ中$(window).load和$(document).ready區(qū)別與執(zhí)行順序
JQ中的$(document).ready()大家應(yīng)該用的非常多,基本每個JS腳本中都有這個函數(shù)的出現(xiàn)有時甚至?xí)霈F(xiàn)多個,那么另一個加載函數(shù)$(window).load相對出現(xiàn)的次數(shù)就很少了,下面為大家介紹一下兩者的區(qū)別與他們的執(zhí)行順序2017-03-03ComponentLoader?與動態(tài)組件實例詳解
這篇文章主要為大家介紹了ComponentLoader?與動態(tài)組件實現(xiàn)實例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-05-05javascript中的箭頭函數(shù)基礎(chǔ)語法及使用場景示例
這篇文章主要為大家介紹了?javascript中的箭頭函數(shù)基礎(chǔ)語法及使用場景示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-07-07