引子
在 前端异样类型及捕捉形式 之后,尝试了本人去封装一下,而后去看了 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 Event
if (isPlainObject(exception) || isEvent(exception)) {format = doSomething4(exception);
return format;
}
format = doSomething5(exception);
return format;
参考资料
- Error mdn