Open hawx1993 opened 7 years ago
前端异常监控主要是解决两大异常情况:
a. 页面中的javascript异常 b. 静态资源异常(使用addEventListener('error', handler, true)来捕获静态资源异常,包括js、img、css等;)
addEventListener('error', handler, true)
Node.js 中推荐的异常处理方式:
由于try/catch无法捕捉异步回调里的异常,Node.js原生提供uncaughtException事件挂到process对象上,用于捕获所有未处理的异常:
try/catch
uncaughtException
process.on('uncaughtException', function(err) { console.error('Error caught in uncaughtException event:', err); });
try...catch
try { throw new Error('出错了!'); } catch (e) { console.log(e.name + ": " + e.message);//Error: 出错了! console.log(e.stack);//Error: 出错了 at (index):29 }
异步函数的异常捕获
因为异步函数的回调是在事件队列里单独拉出来执行的。所以在异步函数外面包裹try-catch是无法捕捉到回调函数里抛出的异常的。因为当回调函数从队列里被拉出来执行的时候try-catch所在的代码块已经执行完毕了。
try { setTimeout(() => { throw new Error('callback error'); }, 0); } catch (e) { console.error('caught callback error'); } console.log('try-catch block ends');
在上述例子中,当回调里的异常被抛出但没被捕获的时候,该异常会直接被主程序所捕获。在浏览器里可以通过window.onerror,在node里通过process.uncaughtException可以捕获此类异常。
window.onerror
process.uncaughtException
window.onerror,是我们在做错误监控中用到比较多的方案。window.onerror包含了try...catch的优势,而try...catch无法捕获的语法错误和全局异常处理,window.onerror都可以做到。不过,由于是全局监测,就会统计到浏览器插件中的 js 异常。
window.onerror 算是一种特别暴力的容错手段,try..catch 也是如此,他们底层的实现就是利用 C/C++ 中的 goto 语句实现,一旦发现错误,不管目前的堆栈有多深,不管代码运行到了何处,直接跑到顶层或者 try..catch 捕获的那一层,这种一脚踢开错误的处理方式并不是很好。
当然,window.onerror 还有一个问题就是浏览器跨域,页面和 js 代码在不同域上时,浏览器出于安全性的考虑,会将异常内容隐藏,我们只能获取到一个简单的 Script Error信息。解决方案也很简单:
Script Error
<script>
Access-Control-Allow-Origin: *
throw new Error(“error message here”)
<script> window.onerror = function () { console.log(arguments) return true; } throw new Error('show error'); </script>
值得一提的是,页面中可能有好几个 script 标签, window.onerror 这个错误监听一定要放到最前头,否则将监听不到错误。如果将throw new Error放前头,throw new Error('show error');将直接报错,也就无法往下执行
throw new Error
throw new Error('show error');
在 Promise 内部使用 reject 方法来处理错误,而不要直接调用 throw Error,这样你不会捕捉到任何的报错信息。
<script> function errorFn() { return new Promise((resolve, reject) => { setTimeout(() => { reject('我可以被捕获') throw Error('永远无法被捕获');//该错误信息无法在catch中捕获 }) }) } Promise.resolve(true).then((resolve, reject) => { return errorFn() }).catch(error => { console.log('捕获异常', error) // 捕获异常 我可以被捕获 }); </script>
执行回调时已经不是处于原本的执行栈了,Error发生在下一轮事件循环中,所以没有被try...catch捕获
.catch()
image 和 script 标签都有 crossorigin 参数,它的作用就是告诉浏览器,我要加载一个外域的资源,添加跨域支持
线上代码我们一般都会进行压缩处理,压缩代码无法定位到错误的具体位置,为了能快速定位错误,我们需要添加sourceMap文件
写的不错,就是有点乱
前端异常监控主要是解决两大异常情况:
a. 页面中的javascript异常
b. 静态资源异常(使用
addEventListener('error', handler, true)
来捕获静态资源异常,包括js、img、css等;)Node.js错误处理
Node.js 中推荐的异常处理方式:
由于
try/catch
无法捕捉异步回调里的异常,Node.js原生提供uncaughtException
事件挂到process对象上,用于捕获所有未处理的异常:☞ 关于
try...catch
的使用try...catch
可以拿到出错的信息,堆栈,出错文件,行号,列号等等。无法捕捉到语法错误,也没法去捕捉全局的异常事件因为异步函数的回调是在事件队列里单独拉出来执行的。所以在异步函数外面包裹try-catch是无法捕捉到回调函数里抛出的异常的。因为当回调函数从队列里被拉出来执行的时候try-catch所在的代码块已经执行完毕了。
在上述例子中,当回调里的异常被抛出但没被捕获的时候,该异常会直接被主程序所捕获。在浏览器里可以通过
window.onerror
,在node里通过process.uncaughtException
可以捕获此类异常。☞ 关于
window.onerror
的使用window.onerror
,是我们在做错误监控中用到比较多的方案。window.onerror
包含了try...catch
的优势,而try...catch
无法捕获的语法错误和全局异常处理,window.onerror
都可以做到。不过,由于是全局监测,就会统计到浏览器插件中的 js 异常。window.onerror
算是一种特别暴力的容错手段,try..catch 也是如此,他们底层的实现就是利用 C/C++ 中的 goto 语句实现,一旦发现错误,不管目前的堆栈有多深,不管代码运行到了何处,直接跑到顶层或者 try..catch 捕获的那一层,这种一脚踢开错误的处理方式并不是很好。当然,
window.onerror
还有一个问题就是浏览器跨域,页面和 js 代码在不同域上时,浏览器出于安全性的考虑,会将异常内容隐藏,我们只能获取到一个简单的Script Error
信息。解决方案也很简单:<script>
标签添加 crossorigin 属性;Access-Control-Allow-Origin: *
HTTP 头;throw new Error(“error message here”)
。值得一提的是,页面中可能有好几个 script 标签,
window.onerror
这个错误监听一定要放到最前头,否则将监听不到错误。如果将throw new Error
放前头,throw new Error('show error');
将直接报错,也就无法往下执行异步(Promise)环境下错误处理方式
在 Promise 内部使用 reject 方法来处理错误,而不要直接调用 throw Error,这样你不会捕捉到任何的报错信息。
执行回调时已经不是处于原本的执行栈了,Error发生在下一轮事件循环中,所以没有被try...catch捕获
try...catch
,直接使用.catch()
try...catch
try...catch
☞ crossOrigin参数跳过跨域限制
image 和 script 标签都有 crossorigin 参数,它的作用就是告诉浏览器,我要加载一个外域的资源,添加跨域支持
☞ 添加sourceMap文件
线上代码我们一般都会进行压缩处理,压缩代码无法定位到错误的具体位置,为了能快速定位错误,我们需要添加sourceMap文件
js原生错误类型