媒介
做好毛病監控,將用戶運用時的毛病日記上報,能夠協助我們更快的處置懲罰一些題目。現在開源的比較好的前端監控有
那前端監控是怎樣完成的呢?要想相識這個,須要曉得前端毛病也許分為哪些以及怎樣捕捉處置懲罰。
前端毛病分為JS運行時毛病、資本加載毛病和接口毛病三種。
一、JS運行時毛病
JS運行時毛病平常運用window.onerror捕捉,然則有一種迥殊狀況就是promise被reject而且毛病信息沒有被處置懲罰的時刻拋出的毛病
1.1 平常狀況的JS運行時毛病
運用window.onerror和window.addEventListener(‘error’)捕捉。个中window.onerror含有細緻的error信息(error.stack),而且兼容性更好,所以平常JS運行時毛病運用window.onerror捕捉處置懲罰
window.onerror = function (msg, url, lineNo, columnNo, error)
{
// 處置懲罰error信息
}
window.addEventListener('error', event =>
{
console.log('addEventListener error:' + event.target);
}, true);
// true代表在捕捉階段挪用,false代表在冒泡階段捕捉。運用true或false都能夠
例子:
https://jsbin.com/lujahin/edit?html,console,output 點擊button拋出毛病,離別被window.onerror和window.addEventListener(‘error’)捕捉
1.2 Uncaught (in promise)
當promise被reject而且毛病信息沒有被處置懲罰的時刻,會拋出一個unhandledrejection,而且這個毛病不會被window.onerror以及window.addEventListener(‘error’)捕捉,須要用特地的window.addEventListener(‘unhandledrejection’)捕捉處置懲罰
window.addEventListener('unhandledrejection', event =>
{
console.log('unhandledrejection:' + event.reason); // 捕捉后自定義處置懲罰
});
https://developer.mozilla.org…
例子:
https://jsbin.com/jofomob/edit?html,console,output 點擊button拋出unhandledrejection毛病,而且該毛病僅能被window.addEventListener(‘unhandledrejection’)捕捉
1.3 console.error
一些迥殊狀況下,還須要捕捉處置懲罰console.error,捕捉體式格局就是重寫window.console.error
var consoleError = window.console.error;
window.console.error = function () {
alert(JSON.stringify(arguments)); // 自定義處置懲罰
consoleError && consoleError.apply(window, arguments);
};
1.4 迥殊申明跨域日記
什麼是跨域劇本error?
https://developer.mozilla.org…
當加載自差別域的劇本中發作語法毛病時,為防止信息泄漏(拜見bug 363897),語法毛病的細節將不會報告,而代之簡樸的”Script error.”。在某些瀏覽器中,經由過程在<script>運用crossorigin屬性並要求服務器發送恰當的 CORS HTTP 相應頭,該行動可被掩蓋。一個變通計劃是零丁處置懲罰”Script error.”,示知毛病概況僅能經由過程瀏覽器控制台檢察,沒法經由過程JavaScript接見。
例子: http://sandbox.runjs.cn/show/… 請翻開頁面翻開控制台。該頁面離別加載了兩個差別域的js劇本,設置了crossorigin的window.onerror能夠報出細緻的毛病,沒有設置crossorigin只能報出’script error’,而且沒有毛病信息
1.5 迥殊申明sourceMap
在線上由於JS平常都是被緊縮或許打包(webpack)過,打包后的文件只要一行,因而報錯會湧現第一行第5000列湧現JS毛病,給排查帶來難題。sourceMap存儲打包前的JS文件和打包后的JS文件之間一個映照關聯,能夠依據打包后的位置疾速解析出對應源文件的位置。
然則出於安全性斟酌,線上設置sourceMap會存在不安全的題目,由於網站運用者能夠隨意馬虎的看到網站源碼,此時能夠設置.map文件只能經由過程公司內網接見下降隱患
sourceMap設置devtool: ‘inline-source-map’
假如運用了uglifyjs-webpack-plugin 必需把 sourceMap設置為true
1.6 別的
1.6.1 sentry把一切的回調函數運用try catch封裝一層
https://github.com/getsentry/raven-js/blob/master/src/raven.js
1.6.2 vue errorHandler
https://vuejs.org/v2/api/#errorHandler
其道理也是運用try catch封裝了nextTick,$emit, watch,data等
https://github.com/vuejs/vue/blob/dev/dist/vue.runtime.js
二、資本加載毛病
運用window.addEventListener(‘error’)捕捉,window.onerror捕捉不到資本加載毛病
https://jsbin.com/rigasek/edit?html,console 圖片資本加載毛病。此時只要window.addEventListener(‘error’)能夠捕捉到
window.onerror和window.addEventListener(‘error’)的異同:相同點是都能夠捕捉到window上的js運行時毛病。區別是1.捕捉到的毛病參數差別 2.window.addEventListener(‘error’)能夠捕捉資本加載毛病,然則window.onerror不能捕捉到資本加載毛病
三、接口毛病
一切http要求都是基於xmlHttpRequest或許fetch封裝的。所以要捕捉全局的接口毛病,要領就是封裝xmlHttpRequest或許fetch
3.1 封裝xmlHttpRequest
if(!window.XMLHttpRequest) return;
var xmlhttp = window.XMLHttpRequest;
var _oldSend = xmlhttp.prototype.send;
var _handleEvent = function (event) {
if (event && event.currentTarget && event.currentTarget.status !== 200) {
// 自定義毛病上報 }
}
xmlhttp.prototype.send = function () {
if (this['addEventListener']) {
this['addEventListener']('error', _handleEvent);
this['addEventListener']('load', _handleEvent);
this['addEventListener']('abort', _handleEvent);
} else {
var _oldStateChange = this['onreadystatechange'];
this['onreadystatechange'] = function (event) {
if (this.readyState === 4) {
_handleEvent(event);
}
_oldStateChange && _oldStateChange.apply(this, arguments);
};
}
return _oldSend.apply(this, arguments);
}
3.2 封裝fetch
if(!window.fetch) return;
let _oldFetch = window.fetch;
window.fetch = function () {
return _oldFetch.apply(this, arguments)
.then(res => {
if (!res.ok) { // True if status is HTTP 2xx
// 上報毛病
}
return res;
})
.catch(error => {
// 上報毛病
throw error;
})
}
結論
- 運用window.onerror捕捉JS運行時毛病
- 運用window.addEventListener(‘unhandledrejection’)捕捉未處置懲罰的promise reject毛病
- 重寫console.error捕捉console.error毛病
- 在跨域劇本上設置crossorigin=”anonymous”捕捉跨域劇本毛病
- window.addEventListener(‘error’)捕捉資本加載毛病。由於它也能捕捉js運行時毛病,為防止反覆上報js運行時毛病,此時只要event.srcElement inatanceof HTMLScriptElement或HTMLLinkElement或HTMLImageElement時才上報
- 重寫window.XMLHttpRequest和window.fetch捕捉要求毛病
應用以上道理,簡樸寫了一個JS監控,只處置懲罰了一些JS毛病,臨時沒有做和機能相干的監控
https://github.com/Lie8466/better-js
假如發明文章有毛病,迎接斧正。