一、為什么要處理異常?
1 增強用戶體驗
2 遠程定位問題
3 未雨綢繆 發現問題
4 無法浮現問題 尤其是移動端 機型 系統都是問題
5 完善的前端方案 前端監控系統
二、需要處理哪些異常
1、js預發錯誤 代碼異常
2、ajax請求異常
3、靜態資源家在異常
4、promise異常
5、iframe異常
6、跨域script error
7、崩潰和卡頓
Try-Catch的誤區
try-catch只能捕獲同步的運行時錯誤。對語法和異步的錯誤無能為力,捕獲不到。
1、同步運行時錯誤
2、不能捕獲具體的語法錯誤,只有一個語法錯誤提示
3、異步錯誤
異步異常 捕獲不到
四、window.onerror不是萬能的
當js運行時錯誤發生時,window會觸發一個ErrorEvent接口的error事件,并執行window.onerror
/**
message: 錯誤信息
source: 出錯文件
lineno: 行號
error: 錯誤對象
*/
window.onerror = function(message, source, lineno, colno, error){
console.log('異常捕獲', {message, source, lineno, colno, error})
}
1、同步信息錯誤
2、語法錯誤
3、模擬異步運行時的錯誤
setTimeout(() => {
michael
}, 3000)
補充一點:window.onerror 函數只有返回true的時候,異常才不會向上拋出,否則控制臺還是會顯示Uncaught Error: XXXXXXXX
注意:
onerror最好寫在所有的js腳本的前面,否則有可能捕獲不到錯誤。
onerror無法捕獲語法錯誤
五、winodw.addEventListener 靜態資源加載異常
當資源加載失敗,加載資源的元素會觸發一個Event接口的error事件,并執行該元素上的onerror處理函數
window.addEventListener('error', function(error){
console.log('捕獲到異常',error)
}, true)
六、Promise Catch
primise中使用catch可以獲取到異步的error, 但是如果忘了怎么辦
解決方案:為了防止有漏掉的Promise異常,建議在全局增加一個對unhandlerejection的監聽,用來全局監聽 Uncaught Promise Error
window.addEventListener('unhandledrejection', function(e) {
e.preventDefault()
console.log(e)
return true
})
Promise.reject('error')
七、vue errorHandler
Vue.config.errorHandler = (err, vm, info) => {
console.error('通過vue errorHandler捕獲的錯誤');
console.error(err);
console.error(vm);
console.error(info);
}
八、react中異常捕獲
componentDidCatch(error, info){
}
注意點:error boundaries并不會捕獲下面錯誤
1、事件處理器
2、異步代碼
3、服務端的渲染代碼
4、在error boundaries區域內的錯誤
九、iframe異常
<iframe src="./frame.html"></iframe>
window.frames[0].onerror = function(message, source, lineno, colno, error){
console.log('異常', { message, source, lineno, colno, error })
return true
}
十、Script error
基本上跨域問題
十一、崩潰和卡頓
利用window對象的load和beforeunload事件實現了網頁崩潰的監控。
window.addEventListener('load', function(){
sessionStorage.setItem('good_exit', 'pending')
setInterval(function(){
sessionStorage.setItem('time_before', new Date().toString())
}, 1000)
})
window.addEventListener('beforeunload', function(){
sessionStorage.setItem('good_exit', 'true')
})
if(sessionStorage.getItem('good_exit') && sessionStorage.getItem('good_exit') !== 'true'){
alert('Hey, welcome back from your crash, looks like you crashed on: ' + sessionStorage.getItem('time_before_crash'))
}
2、基于以下原因,我們可以使用 Service Worker 來實現網頁崩潰的監控:
Service Worker 有自己獨立的工作線程,與網頁區分開,網頁崩潰了,Service Worker 一般情況下不會崩潰;Service Worker 生命周期一般要比網頁還要長,可以用來監控網頁的狀態;網頁可以通過 navigator.serviceWorker.controller.postMessage API 向掌管自己的 SW 發送消息。
十二 錯誤上報
1、通過ajax 風險:ajax本身也有報錯風險,跨域問題
2、動態創建img標簽的形式
function report(error){
let url = 'http://www.baicuu.com'
new Image().src = `${url}?logs=${error}`
}
收集信息太多怎么辦?如何減少服務器的壓力
Report.send = function(data){
if(Math.random < 0.3) {
send(data)
}
}
視情況定,用戶特征等等
十三 總結
如何優雅的處理異常
1、可疑區增加try-catch
2、全局監控js異常
3、全局監控靜態資源異常 window.addEventListener
4、
5、
6、監控網頁崩潰:window對象的load 和 beforeunload
7、跨域crossOrigin
分類型解決異常