前端一直是离用户最近的一层。随着产品的改进,我们会更加注重用户体验,但是前端异常总是令人讨厌。
4.接下来,我们来试试异常网络请求:
<>window. = function(message, source, lineno, colno, error) {console.log('捕获到异常:',{message, source, lineno, colno, error});return true;}</><img src="./jartto.png "/>& lt>。窗户。= function (message,source,lineno,colno,error){ console . log(' exception cated:',{message,source,lineno,colno,error });返回true} & lt/>。& ltimg src= "。/jartto.png "/>
由于网络请求异常不会冒泡,因此必须在捕获阶段捕获它们。但是这种方法虽然可以捕捉网络请求异常,但是无法判断HTTP的状态是404还是500等其他,需要配合服务器日志进行故障排除和分析。
需要注意的是:
不同浏览器下返回的 error 对象可能不同,需要注意兼容处理。需要注意避免 addEventListener 重复监听。六、Promise Catch使用catch in promise可以轻松捕获异步错误,这非常简单。
没有捕获的承诺中抛出的错误不能被或try-catch捕获,所以我们一定不要忘记编写catch来处理承诺中抛出的异常。
解决方案:为了防止遗漏承诺异常,建议添加一个全局未处理的监控程序来全局监控未承诺错误。用法:
window . addeventlistener(" unhandledreprojection ",函数(e){ console . log(e);});
让我们继续尝试:
Window.addeventlistener("未处理的拒绝",函数(e){ e . prevent default(). console . log('捕获的异常:',e);返回true});promise . reject(' promise error ');
您可以看到以下输出:
没抓到Promise怎么办?
Window.addeventlistener("未处理的拒绝",函数(e){ e . prevent default(). console . log('捕获的异常:',e);返回true});新承诺((解决,拒绝)= >;{ reject(' jar tto:promise error ');});
嗯,原来会正常捕捉。
因此,如上所述,为了防止遗漏promise异常,建议添加一个全局监视器来监视全局未处理的Promise错误。
还有一点:如果你去掉了控制台的异常显示,你需要添加:
event . PreventDefault();七、vue error handler vue . config . error handler =(err,VM,info)= >;{ console . error(' vue ErrorHandler捕获的错误');console . error(err);console . error(VM);console . error(info);}八。捕捉反应异常
React 16提供了一个内置函数,componentDidCatch,可以很容易的得到React下的错误信息
componentDidCatch(错误,信息){console.log(错误,信息);}
另外,我们可以理解,错误边界UI的某些部分导致的JS错误不应该破坏整个程序。为了帮助React用户解决这个问题,React 16引入了一个关于错误边界的新概念。
注意:错误边界不会捕捉以下错误。
1.事件处理程序2。异步代码3。呈现服务器4的代码。错误边界区域中的错误
让我们举一个小例子,下面componentidcatch (error,info)中的类将成为一个错误边界:
类错误边界扩展了反应。组件{构造器(道具){super(道具);this . state = { hasError:false };} componentDidCatch(错误,信息){//Display fallback uithis . setstate({ hasError:true });//您也可以将错误记录到错误报告服务日志错误服务(错误,信息);} render(){ if(this . state . haserror){//您可以呈现任何自定义的回退UIreturn & ltp>。出事了。& lt/p>。;}返回this . props . children;}}
然后我们像普通组件一样使用它:
& lt错误边界>。& ltMyWidget />& lt/ErrorBoundary>。
componentDidCatch()方法的工作方式类似于JS的catch{}模块,但是对于组件来说,只有类组件可以成为错误边界。
其实大多数情况下,我们可以在整个程序中定义一个错误边界组件,然后就可以一直使用了!
九.iframe不正常
对于iframe的异常捕获,我们必须使用window。:
窗户。= function (message,source,lineno,colno,error){ console . log(' exception cated:',{message,source,lineno,colno,error });}
一个简单的例子如下:
& ltiframe src= "。/iframe . html " frame border = " 0 " & gt。& lt/iframe>。& lt>。Window.frames [0]。= function (message,source,lineno,colno,error){ console . log(' iframe exception cated:',{message,source,lineno,colno,error });返回true};& lt/>。十.错误
一般如果出现error等错误,基本可以确定是跨域问题。此时不会有其他辅助信息,但解决方案无非如下:
跨来源资源共享机制(CORS):我们将跨来源属性添加到标签中。
& ltsrc = " http://jartto . Wang/main . js " cross origin & gt;& lt/>。
或者动态添加js脚本:
const =文档。('');。crossOrigin = ' anonymous。src = urldocument . body(.);
特别是服务器需要设置:访问控制允许源
此外,我们还可以尝试这种解决错误的替代方法:
const OriginaddEventListener = EventTarget . prototype . AddEventListener;event target . prototype . addevent listener = function(类型,侦听器,选项){const wrappedListener = function(...args){ try { return listener . apply(this,args);} catch(err){ throw err;} }返回Originaddeventlistener . call(this,type,wrappedListener,options);}
简单解释一下:
改写了 EventTarget 的 addEventListener 方法;对传入的 listener 进行包装,返回包装过的 listener,对其执行进行 try-catch;浏览器不会对 try-catch 起来的异常进行跨域拦截,所以 catch 到的时候,是有堆栈信息的;重新 throw 出来异常的时候,执行的是同域代码,所以 window. 捕获的时候不会丢失堆栈信息;通过包装addEventListener,我们还可以达到“扩展堆栈”的效果:
(()= >;{ const OriginaddeventListener = EventTarget . prototype . AddEventListener;event target . prototype . addevent listener = function(type,listener,options){+//添加事件时捕获堆栈+const add stack = new error(` event($ { type })`)。堆栈;const wrappedListener =函数(...args){ try { return listener . apply(this,args);}catch (err) {+ //发生异常时,扩展堆栈+err . stack+= ' n '+addStack;抛出err} }返回Originaddeventlistener . call(this,type,wrappedListener,options);}})();十一、坍塌和卡住
卡住,就是网页暂时反应慢,JS可能执行不及时。但是崩溃是不同的。所有网页崩溃,JS不起作用。我们还有什么方法可以监控网页崩溃并报告?
崩溃和卡住是不可忽视的,可能会导致你的用户流失。
1.利用window对象的load和beforeunload事件,实现了网页崩溃监控。好文章,推荐阅读:记录浏览器崩溃信息。
window.addEventListener('load ',function(){ sessionstorage . setitem(' good _ exit ',' pending ');setInterval(function(){ session storage . setitem(' time _ before _ crash ',new Date()。toString());}, 1000);});window . addevent listener(' before unload ',function(){ sessionstorage . setitem(' good _ exit ',' true ');});if(session storage . GetItem(' good _ exit ')& amp;& ampsession storage . GetItem(' good _ exit ')!= = ' true '){/*在此处插入崩溃日志记录代码*/alert('嘿,欢迎您从崩溃中回来,看起来您崩溃了:'+session storage . getitem(' time _ before _ crash ');}
2.基于以下原因,我们可以使用服务工作器来监控网页崩溃:
Service Worker 有自己独立的工作线程,与网页区分开,网页崩溃了,Service Worker 一般情况下不会崩溃;Service Worker 生命周期一般要比网页还要长,可以用来监控网页的状态;网页可以通过 navigator.serviceWorker.controller.postMessage API 向掌管自己的 SW 发送消息。十二、错误上报1.通过 Ajax 发送数据因为 Ajax 请求本身也有可能会发生异常,而且有可能会引发跨域问题,一般情况下更推荐使用动态创建 img 标签的形式进行上报。1.通过Ajax发送数据,因为Ajax请求本身可能是异常的,可能会造成跨域的问题。通常,建议使用动态创建img标签的形式进行报告。
2.动态创建 img 标签的形式2.动态创建img标签表单
函数report(error){ let report URL = ' http://jar tto . Wang/report ';新图像()。src = `${reportUrl}?logs = $ { error } `;}
收集了太多异常信息,怎么办?其实我们要考虑这样一种情况:如果你的网站访问量很大,那么不可避免的一个错误就会发出很多信息。此时,我们需要设置收集速率来减轻服务器的压力:
记者。send = function(data){//仅30% if (math。随机()
收藏率要根据实际情况设定,随机数或者一些用户特征都是不错的选择。
十三.总结
回到我们一开始提出的问题,如何优雅地处理异常?
1.尝试捕获被添加到可疑区域
2.全局监控JS异常窗口。
3.静态资源异常窗口的全局监控
4.没有捕获的捕获承诺异常:未处理的拒绝
5.VUE错误处理器和反应组件捕获
6.监控网页崩溃:窗口对象加载和卸载前
7.跨域跨原点解决方案
其实很简单,如上所述:采用组合方案,按类型捕捉异常,让80%-90%的问题基本看不见。
通过
http://jartto.wang/2018/11/20/js-exception-handling/
1.《网页上有错误怎么解决 如何优雅处理前端异常?》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。
2.《网页上有错误怎么解决 如何优雅处理前端异常?》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。
3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/tiyu/1035005.html