Error 类
1. Error 分类
- Error : 通用的错误类型,如: new Error(‘error!!!’)
- SyntaxError : 语法错误,如: require(‘vm’).runInThisContext(‘binary ! isNotOk’)
- ReferenceError : 引用错误,如引用一个未定义的变量,如: doesNotExist
- TypeError : 类型错误,如: require(‘url’).parse(() => { });
- URIError : 全局的 URI 处理函数抛出的错误,如: encodeURI(’\uD800’)
- AssertError : 使用 assert 模块时抛出的错误,如: assert(false)
2. Error 对象
new Error(message) 会生成一个 Error 对象
- error.code:定义 error 的类型,系统抛出的异常会有相关 code 定义,用户有需求,要自己给 error 设置code
- error.message:消息错误描述
- error.stack:错误堆栈跟踪信息
3. Error.captureStackTrace(targetObject[, constructorOpt])
该函数捕获 targetObject 调用栈,只能使用在 V8 引擎上:
//captureStackTrace 会给 targetObject 设置 stack 属性,用于获取 targetObject 的调用栈信息
const myObject = {
};
Error.captureStackTrace(myObject);
myObject.stack; // similar to `new Error().stack`
与 new Error().stack 的区别:
- 无需new一个新的Error对象,节省内存空间,同时代码上也会更加优雅。
- 如果使用Error.captureStackTrace,则对于堆栈信息的格式化工作会被延迟至访问targetObj.stack时进行,如果targetObj.stack未被访问,则堆栈信息的格式化工作会被省略,从而节省计算资源
4. Error.prepareStackTrace(error, structuredStackTrace)
- 该方法可以定制 Error 对象的 stack 信息
- 第一个参数error对象本身,第二个参数是调用栈信息数组
- Error 默认情况下返回的 stack 信息是一个字符串,我们可以通过该函数进行定制化处理,格式化等操作
- 这个方法是 V8 暴露出来的,所以只能在基于 V8 的 Node.js 或者 Chrome 里才能使用。
- 这个方法会修改全局 Error 的行为,所以如果局部修改 Error 行为的话,需要先把原先的 Error.prepareStackTrace,方便复原默认行为
- callSite是一个对象,其中包括很多有用的函数如下:
- getThis : returns the value of this
- getTypeName : returns the type of this as a string. This is the name of the function stored in the constructor field of this, if available, otherwise the - - - - object's [[Class]]internal property.
- getFunction : returns the current function
- getFunctionName : returns the name of the current function, typically its name property. If a name property is not available an attempt will be made to try to infer a name from the function's context.
- getMethodName : returns the name of the property of this or one of its prototypes that holds the current function
- getFileName : if this function was defined in a script returns the name of the script
- getLineNumber : if this function was defined in a script returns the current line number
- getColumnNumber : if this function was defined in a script returns the current column number
- getEvalOrigin : if this function was created using a call to eval returns a CallSite object representing the location where eval was called
- isToplevel : is this a toplevel invocation, that is, is this the global object?
- isEval : does this call take place in code defined by a call to eval?
- isNative : is this call in native V8 code?
- isConstructor : is this a constructor call?
// 报错默认行为
let oldPrepareStackTrace = Error.prepareStackTrace;
Error.prepareStackTrace = function (error, callSites) {
return error.toString() + '\n' + callSites.map(callSite => {
return ' -> ' + callSite.getFunctionName() + ' ('
+ callSite.getFileName() + ':'
+ callSite.getLineNumber() + ':'
+ callSite.getColumnNumber() + ')'
}).join('\n')
}
/*do something*/
// 复原默认行为
Error.prepareStackTrace = oldPrepareStackTrace;
5. Error.stackTraceLimit
可以修改堆栈信息的深度,默认为10。
6. Long Stack Trace
Node.js 中有很多异步操作,问题出在异步操作,当遇到异步回调就会丢失绑定回调前的调用栈信息:
//这段代码就会丢失 bar 函数的调用栈
var foo = function () {
throw new Error('error!!!')
}
var bar = function () {
setTimeout(foo)
}
bar()
/Users/nswbmw/Desktop/test/app.js:2
throw new Error('error!!!')
^
Error: error!!