錯(cuò)誤異常發(fā)生
- 頁(yè)面js報(bào)錯(cuò)
- 請(qǐng)求報(bào)錯(cuò)
- 頁(yè)面資源加載報(bào)錯(cuò)
- promise異常
- iframe加載異常
- 頁(yè)面奔潰&卡頓異常
處理異常的方法
1、react 自帶的errorBoundaries
2、 react 自定義Hooks
3、 vue errorHandler
4、try catch 對(duì)特定的代碼進(jìn)行捕獲
5、window.addEventListerner
6、window.onerror
7、 window.unhandledrejection
8、 iframe錯(cuò)誤處理
9、跨域錯(cuò)誤處理
10、頁(yè)面奔潰卡頓處理
11、 統(tǒng)一上報(bào)錯(cuò)誤(不會(huì)有跨域問(wèn)題
ps: 在開(kāi)發(fā)環(huán)境下,語(yǔ)法錯(cuò)誤一般會(huì)在編輯器中直接拋出,導(dǎo)致程序奔潰,能夠得到及時(shí)的處理。
1、react errorBoundaries錯(cuò)誤邊界
可以捕獲發(fā)生在其子組件樹(shù)任何位置的 JavaScript 錯(cuò)誤,并打印這些錯(cuò)誤,同時(shí)展示降級(jí) UI.
而并不會(huì)渲染那些發(fā)生崩潰的子組件樹(shù)。錯(cuò)誤邊界可以捕獲發(fā)生在整個(gè)子組件樹(shù)的渲染期間、生命周期方法以及構(gòu)造函數(shù)中的錯(cuò)誤。
引用官方文檔實(shí)例:
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
// 更新 state 使下一次渲染能夠顯示降級(jí)后的 UI
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
// 你同樣可以將錯(cuò)誤日志上報(bào)給服務(wù)器
logErrorToMyService(error, errorInfo);
}
render() {
if (this.state.hasError) {
// 你可以自定義降級(jí)后的 UI 并渲染
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
無(wú)法捕獲到的錯(cuò)誤:
事件處理
異步代碼(setTimeout或requestAnimationFrame回調(diào)函數(shù))
服務(wù)端渲染
自身拋出來(lái)的錯(cuò)誤
2、react 自定義Hooks
const useThrowAsyncError = () => {
const [state, setState] = useState();
return (error) => {
setState(() => throw error)
}
}
使用:引入該hook
throwAsyncError(e)
自己封裝hook,然后自己去調(diào)用setState throw把錯(cuò)誤拋出去,調(diào)用setState會(huì)重新渲染,就會(huì)把錯(cuò)誤拋出去,就是在渲染周期內(nèi)了,errorBoundaries就能捕獲到了
3、errorHandler
vue主要是通過(guò)errorCaptured鉤子來(lái)捕獲錯(cuò)誤,通過(guò)errorHandler處理錯(cuò)誤。
errorCaptured是捕獲一個(gè)來(lái)自子孫組件的錯(cuò)誤時(shí)被調(diào)用。
vue.config.errorHandler((err, vm, info) => {
// err錯(cuò)誤對(duì)象
// vm 發(fā)生錯(cuò)誤的組件實(shí)例
// info 一個(gè)包含錯(cuò)誤來(lái)源信息的字符串
// false 該錯(cuò)誤不會(huì)繼續(xù)向上傳播
return false
})
只能捕獲到同步的代碼錯(cuò)誤,異步錯(cuò)誤需要用到裝飾器。
4、 try catch 對(duì)特定的代碼進(jìn)行捕獲
try-catch適合處理一些無(wú)法控制的錯(cuò)誤,比如網(wǎng)絡(luò)請(qǐng)求、各種I/O操作等。將代碼中有可能發(fā)生錯(cuò)誤的放在try語(yǔ)句塊中,一旦發(fā)生異常,就將控制權(quán)轉(zhuǎn)交給catch塊執(zhí)行,然后繼續(xù)執(zhí)行后續(xù)任務(wù),不會(huì)阻塞進(jìn)程。
try{
//可能發(fā)生錯(cuò)誤代碼
} catch (err) {
// 捕獲
}
但try中發(fā)生的錯(cuò)誤及異步任務(wù)、語(yǔ)法錯(cuò)誤,catch捕獲不到
5、 window.addEventListerner
<script>
window.addEventListener('error', (error) => {
console.log('捕獲到異常:', error);
}, true)
</script>
<img src="./xxxx.png">
返回的是errorEvent事件對(duì)象
6. window.onerror
js運(yùn)行時(shí),沒(méi)有被try.catch捕獲到的,一般會(huì)在window.onerror中捕獲到
/**
* @param {String} message 錯(cuò)誤信息
* @param {String} source 出錯(cuò)文件
* @param {Number} lineno 行號(hào)
* @param {Number} colno 列號(hào)
* @param {Object} error Error對(duì)象(對(duì)象)
*/
window.onerror = function(message, source, lineno, colno, error) {
console.log('捕獲到異常:',{message, source, lineno, colno, error});
return true
}
1.window.onerror 函數(shù)只有在返回 true 的時(shí)候,異常才不會(huì)向上拋出(瀏覽器接收后報(bào)紅),否則即使是知道異常的發(fā)生控制臺(tái)還是會(huì)顯示 Uncaught Error: xxxxx
2.window.onerror 最好寫(xiě)在所有JS腳本的前面,否則有可能捕獲不到錯(cuò)誤
3.window.onerror無(wú)法捕獲語(yǔ)法錯(cuò)誤
7. unhandledrejection
當(dāng) Promise 被 reject 且沒(méi)有 reject 處理器的時(shí)候,會(huì)觸發(fā) unhandledrejection 事件;這可能發(fā)生在 window 下,但也可能發(fā)生在 Worker 中。發(fā)生在promise塊中的錯(cuò)誤,無(wú)論是否catch,都會(huì)觸發(fā)unhandledrejection事件。
window.addEventListener("unhandledrejection", event => {
console.warn(`UNHANDLED PROMISE REJECTION: ${event.reason}`);
});
window.onunhandledrejection=function()=>{}
8. iframe錯(cuò)誤處理
window.frame[0].onerror = function(message, source) => {}
9、跨域錯(cuò)誤處理
script Error?當(dāng)引用第三方script的時(shí)候,腳本出現(xiàn)錯(cuò)誤,直接提示“script error”。
解決1:設(shè)置crossorigin=”anonymous”,在非同源情況下,設(shè)置 “anonymous” 關(guān)鍵字將不會(huì)通過(guò) cookies,客戶(hù)端 SSL 證書(shū)或 HTTP 認(rèn)證交換用戶(hù)憑據(jù)。但是這個(gè)屬性并不是所有瀏覽器都支持(CORS settings attributes - HTML(超文本標(biāo)記語(yǔ)言))。
解決2:將第三方腳本方法放在try-catch里。
10、頁(yè)面奔潰卡頓處理
1.利用 window 對(duì)象的 load 和 beforeunload 事件實(shí)現(xiàn)了網(wǎng)頁(yè)崩潰的監(jiān)控。
不錯(cuò)的文章,推薦閱讀:http://jasonjl.me/blog/2015/06/21/taking-action-on-browser-crashes/。
window.addEventListener('load', function () {
sessionStorage.setItem('good_exit', 'pending');
setInterval(function () {
sessionStorage.setItem('time_before_crash', new Date().toString());
}, 1000);
});
window.addEventListener('beforeunload', function () {
sessionStorage.setItem('good_exit', 'true');
});
if(sessionStorage.getItem('good_exit') &&
sessionStorage.getItem('good_exit') !== 'true') {
/*
insert crash logging code here
*/
alert('Hey, welcome back from your crash, looks like you crashed on: ' + sessionStorage.getItem('time_before_crash'));
}
11、統(tǒng)一上報(bào)錯(cuò)誤(不會(huì)有跨域問(wèn)題)
利用img 的 src請(qǐng)求不跨域
function report(error) {
const reportUrl = 'http://xxx/report/'
new Image().src = `${reportUrl}?logs=${error}`
}
ps: img的src和script的src: 原理是相同的,都是利用標(biāo)簽的src屬性可以跨域請(qǐng)求的特點(diǎn),但是不同的是:
使用img標(biāo)簽不能訪問(wèn)服務(wù)器返回的響應(yīng)內(nèi)容,也就是說(shuō)只能單向的發(fā)送get請(qǐng)求;
而使用script標(biāo)簽實(shí)現(xiàn)的jsonp跨域可以將服務(wù)器響應(yīng)文本以函數(shù)參數(shù)的形式返回,瀏覽器解析js代碼時(shí)直接就執(zhí)行了。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-603570.html
總結(jié):
1、可疑代碼添加 try…catch
2、全局監(jiān)控JS異常: window.onerror
3、全局監(jiān)控靜態(tài)資源異常: window.addEventListener
4、全局捕獲沒(méi)有 catch 的 promise 異常:unhandledrejection
5、iframe 異常:window.error
6、VUE errorHandler 和 React componentDidCatch
7、監(jiān)控網(wǎng)頁(yè)崩潰:window 對(duì)象的 load 和 beforeunload
8、Script Error 跨域用 crossOrigin 解決
9、統(tǒng)一錯(cuò)誤上報(bào),通過(guò)new image().src文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-603570.html
到了這里,關(guān)于前端異常錯(cuò)誤處理(包括但不限于react,vue)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!