引子
在 前端异样类型及捕捉形式 之后,尝试了本人去封装一下,而后去看了 sentry 的源码,发现之前的那篇只是一个概括,当采集的时候,须要更加粗疏的解析,接下来看看各种异样具体是什么样的。
- Origin
- My GitHub
根底知识点
前端异样肯定会接触到 Error
对象,先来简略的理解一下。
谬误的类型:
- Error : 基类型,其它谬误类型都是继承自该类型。
- EvalError : 应用
eval()
函数而产生异样时抛出。 - RangeError : 数值超出相应无效范畴时的异样。
- ReferenceError : 拜访有效的援用的异样。
- SyntaxError : 语法错误的异样。
- TypeError : 变量或参数不是一个无效类型的异样。
- URIError :
encodeURI()
或decodeURI()
传入有效参数的异样。 - AggregateError : 一个操作导致多个异样须要报告,例如
Promise.any()
。 - InternalError : JavaScript 引擎外部抛出的谬误,这个还没有标准化。
实例共有的规范属性:
- message : 异样信息。
- name : 异样名称。
实例共有的非标准属性:
- description : 微软的非标准属性,相似 message 。
- number : 微软的非标准属性,异样数字。
- fileName : Mozilla 的非标准属性,异样产生所在文件的门路。
- lineNumber : Mozilla 的非标准属性,异样产生所在文件的行数。
- columnNumber : Mozilla 的非标准属性,异样产生所在文件的列数。
- stack : Mozilla 的非标准属性,堆栈跟踪。
更多异样相干的信息见 ecma-262 Error 和 WebIDL Exceptions 。
上面看看每种类型的示例。(暂没有思考框架)
以下示例环境:
- Chrome :86.0.4240.198(正式版本) (x86_64)。
- 应用 nginx 启动了一个本地服务,原生 js 。
- 为了不便查看更多信息,应用了 try-catch、onerror、onunhandledrejection 。
EvalError
EvalError
已不再被 JavaScript 抛出,当初该对象为了放弃兼容性存在。用上面的形式能够看到这种异样:
try { throw new EvalError('Hello, EvalError');} catch (e) { console.log(e instanceof EvalError); // true console.log(e.message); // "Hello, EvalError" console.log(e.name); // "EvalError"}
查一些材料说上面形式就会抛出该类型异样,但试了一下抛出的异样是 TypeError
。
new eval();
RangeError
const arr = new Array(-10)
ReferenceError
let a = undefinedVariable
SyntaxError
eval('hello syntax')
有些语法错误是无奈捕捉的,因为可能导致整个程序无奈失常运行,不过这类型大多在编写阶段就会很容易发现。
const a++;
TypeError
const a = 'hell';a.fun();
URIError
decodeURIComponent('%')
AggregateError
Promise.any([ Promise.reject(new Error("some error")),]).catch(e => { throw e; // 这里抛出,让 onunhandledrejection 接管会有具体的异样信息});
DOMException
const node = document.querySelector('#demo'); // 这个要存在const refnode = node.nextSibling;const newnode = document.createTextNode('异样');node.insertBefore(newnode, refnode);
DOMError
曾经不举荐应用了,但一些浏览器还是兼容了这个。
const err = new DOMError('DOMError');throw err;
ErrorEvent
const err = new ErrorEvent('ErrorEvent');throw err; // onerror 会捕捉到
资源加载异样
常见的 link
、script
、img
标签加载异样都是这样相似的信息:
接口申请异样
根底 XMLHttpRequest
示例:
const xhr = new XMLHttpRequest();xhr.open("GET", "http://localhost:6677/index");xhr.onreadystatechange = function() { if (xhr.readyState == 4) { if (xhr.status == 200) { console.info('success') } else { console.info('xhr error:',xhr) } }};xhr.send();
根底 fetch
示例:
fetch("http://localhost:6677/index").then((res) => { if (!res.ok) { throw res; }}).catch((e) => { console.info('fetch error:',e);})
Script error.
这个本地(浏览器间接文件门路拜访)很容易呈现,例如点击按钮的时候,抛出了一个异样,onerror
也捕捉到了,但什么信息也没有:
换成 try-catch
捕捉,有了一些信息:
这个应该是一个对象,用对象的模式打印一下:
这样就能够拿到相干的信息进行解析了,可参考 TraceKit 。
辨别
看到下面的示例,有好几种模式的异样,进行解决的时候,辨别判断的根据是什么?
思路 1
比较简单的做法,就是不必辨别,既然都是异样,整个全都上报,在后盾人工查看一样能够达到异样剖析排查的目标。
思路 2
通过查看特定字段,或者字段的组合来判断辨别。针对特定的异样能够做到,所有的就不太分明了。
思路 3
在看 sentry 源码的时候,发现了另外一种思路:依据异样的类型来辨别。
应用的次要办法是:
function getType(value) { return Object.prototype.toString.call(value);}
依照这个思路,异样类型有:
- [object Error] : 属于这种类型的异样有
RangeError
、ReferenceError
、SyntaxError
、TypeError
、URIError
。 - [object Exception] : 这个没找到,但 sentry 外面有写。
- [object DOMException] : 属于这种类型的异样有
DOMException
。 - [object DOMError] : 属于这种类型的异样有
DOMError
。 - [object ErrorEvent] : 属于这种类型的异样有
ErrorEvent
。 - [object PromiseRejectionEvent] : 这个有些非凡,当下面的 AggregateError 在
catch
外面查看类型时属于[object Error]
,如果throw
时,在onunhandledrejection
外面类型变成了[object PromiseRejectionEvent]
。
这里大略的写一下 sentry 的辨别逻辑:
const exception = 'some value';let format;if (isErrorEvent(exception) && exception.error) { format = doSomething1(exception); return format;}if (isDOMError(exception) || isDOMException(exception)) { format = doSomething2(exception); return format;}// isError 蕴含的类型有 [object Error] [object Exception] [object DOMException] ,以及继承自 Error 对象的自定义对象。if (isError(exception)) { format = doSomething3(exception); return format;}// isPlainObject 查看类型是 [object Object],isEvent查看的是 wat instanceof Eventif (isPlainObject(exception) || isEvent(exception)) { format = doSomething4(exception); return format;}format = doSomething5(exception);return format;
参考资料
- Error mdn