我想在我的JS代码中抛出一些东西,我想让它们成为instanceof Error,但我也想让它们成为其他东西。
在Python中,通常会子类化Exception。
在JS中应该做什么?
我想在我的JS代码中抛出一些东西,我想让它们成为instanceof Error,但我也想让它们成为其他东西。
在Python中,通常会子类化Exception。
在JS中应该做什么?
当前回答
编辑:请阅读评论。我的目的是提供一个跨浏览器的解决方案,它可以在所有浏览器中工作,并在支持的地方提供堆栈跟踪。
编辑:我创建这个社区维基是为了允许更多的编辑。
V8 (Chrome / Node.JS)的解决方案,在Firefox中工作,并可以修改为在IE中正常工作。(见文末)
function UserError(message) {
this.constructor.prototype.__proto__ = Error.prototype // Make this an instanceof Error.
Error.call(this) // Does not seem necessary. Perhaps remove this line?
Error.captureStackTrace(this, this.constructor) // Creates the this.stack getter
this.name = this.constructor.name; // Used to cause messages like "UserError: message" instead of the default "Error: message"
this.message = message; // Used to set the message
}
“让我看看代码!”
短版:
function UserError(message) {
this.constructor.prototype.__proto__ = Error.prototype
Error.captureStackTrace(this, this.constructor)
this.name = this.constructor.name
this.message = message
}
我保留这个。构造器。原型。__proto__ =错误。函数中的原型将所有代码保存在一起。但是你也可以替换这个。使用UserError构造函数,这允许你将代码移到函数之外,所以它只被调用一次。
如果您走那条路,请确保在第一次抛出UserError之前调用该行。
这个警告并不适用于函数,因为函数是先创建的,不管顺序如何。因此,您可以将函数移动到文件的末尾,没有任何问题。
浏览器兼容性
工作在Firefox和Chrome(和Node.JS),并满足所有承诺。
ie浏览器出现如下问题
Errors do not have err.stack to begin with, so "it's not my fault". Error.captureStackTrace(this, this.constructor) does not exist so you need to do something else like if(Error.captureStackTrace) // AKA if not IE Error.captureStackTrace(this, this.constructor) toString ceases to exist when you subclass Error. So you also need to add. else this.toString = function () { return this.name + ': ' + this.message } IE will not consider UserError to be an instanceof Error unless you run the following some time before you throw UserError UserError.prototype = Error.prototype
其他回答
我会退一步考虑你为什么要这么做?我认为关键是要以不同的方式处理不同的错误。
例如,在Python中,您可以限制catch语句仅捕获MyValidationError,也许您希望能够在javascript中执行类似的操作。
catch (MyValidationError e) {
....
}
你不能在javascript中这样做。只有一个捕捉块。你应该对错误使用if语句来确定它的类型。
抓住(e) { 如果(isMyValidationError (e)) { ... }其他{ //可能重新抛出? 把e; } }
我想我会抛出一个原始对象,其中包含类型、消息和您认为合适的任何其他属性。
throw { type: "validation", message: "Invalid timestamp" }
当你捕捉到错误时:
catch(e) {
if(e.type === "validation") {
// handle error
}
// re-throw, or whatever else
}
编辑:请阅读评论。我的目的是提供一个跨浏览器的解决方案,它可以在所有浏览器中工作,并在支持的地方提供堆栈跟踪。
编辑:我创建这个社区维基是为了允许更多的编辑。
V8 (Chrome / Node.JS)的解决方案,在Firefox中工作,并可以修改为在IE中正常工作。(见文末)
function UserError(message) {
this.constructor.prototype.__proto__ = Error.prototype // Make this an instanceof Error.
Error.call(this) // Does not seem necessary. Perhaps remove this line?
Error.captureStackTrace(this, this.constructor) // Creates the this.stack getter
this.name = this.constructor.name; // Used to cause messages like "UserError: message" instead of the default "Error: message"
this.message = message; // Used to set the message
}
“让我看看代码!”
短版:
function UserError(message) {
this.constructor.prototype.__proto__ = Error.prototype
Error.captureStackTrace(this, this.constructor)
this.name = this.constructor.name
this.message = message
}
我保留这个。构造器。原型。__proto__ =错误。函数中的原型将所有代码保存在一起。但是你也可以替换这个。使用UserError构造函数,这允许你将代码移到函数之外,所以它只被调用一次。
如果您走那条路,请确保在第一次抛出UserError之前调用该行。
这个警告并不适用于函数,因为函数是先创建的,不管顺序如何。因此,您可以将函数移动到文件的末尾,没有任何问题。
浏览器兼容性
工作在Firefox和Chrome(和Node.JS),并满足所有承诺。
ie浏览器出现如下问题
Errors do not have err.stack to begin with, so "it's not my fault". Error.captureStackTrace(this, this.constructor) does not exist so you need to do something else like if(Error.captureStackTrace) // AKA if not IE Error.captureStackTrace(this, this.constructor) toString ceases to exist when you subclass Error. So you also need to add. else this.toString = function () { return this.name + ': ' + this.message } IE will not consider UserError to be an instanceof Error unless you run the following some time before you throw UserError UserError.prototype = Error.prototype
就像有些人说的,ES6很简单:
class CustomError extends Error { }
所以我在我的应用程序(Angular, Typescript)中尝试了这个,但它不起作用。经过一段时间后,我发现问题来自Typescript:O
参见https://github.com/Microsoft/TypeScript/issues/13965
这很令人不安,因为如果你这样做:
class CustomError extends Error {}
try {
throw new CustomError()
} catch(e) {
if (e instanceof CustomError) {
console.log('Custom error');
} else {
console.log('Basic error');
}
}
在节点中或直接在浏览器中显示:自定义错误
尝试在你的项目中使用Typescript在Typescript游乐场上运行,它会显示基本错误…
解决方法如下:
class CustomError extends Error {
// we have to do the following because of: https://github.com/Microsoft/TypeScript/issues/13965
// otherwise we cannot use instanceof later to catch a given type
public __proto__: Error;
constructor(message?: string) {
const trueProto = new.target.prototype;
super(message);
this.__proto__ = trueProto;
}
}
为了避免针对每种不同类型的错误的样板文件,我将一些解决方案的智慧结合到createErrorType函数中:
function createErrorType(name, init) {
function E(message) {
if (!Error.captureStackTrace)
this.stack = (new Error()).stack;
else
Error.captureStackTrace(this, this.constructor);
this.message = message;
init && init.apply(this, arguments);
}
E.prototype = new Error();
E.prototype.name = name;
E.prototype.constructor = E;
return E;
}
然后,您可以轻松地定义新的错误类型,如下所示:
var NameError = createErrorType('NameError', function (name, invalidChar) {
this.message = 'The name ' + name + ' may not contain ' + invalidChar;
});
var UnboundError = createErrorType('UnboundError', function (variableName) {
this.message = 'Variable ' + variableName + ' is not bound';
});
这段代码显示了这一切。
function add(x, y) {
if (x && y) {
return x + y;
} else {
/**
*
* the error thrown will be instanceof Error class and InvalidArgsError also
*/
throw new InvalidArgsError();
// throw new Invalid_Args_Error();
}
}
// Declare custom error using using Class
class Invalid_Args_Error extends Error {
constructor() {
super("Invalid arguments");
Error.captureStackTrace(this);
}
}
// Declare custom error using Function
function InvalidArgsError(message) {
this.message = `Invalid arguments`;
Error.captureStackTrace(this);
}
// does the same magic as extends keyword
Object.setPrototypeOf(InvalidArgsError.prototype, Error.prototype);
try{
add(2)
}catch(e){
// true
if(e instanceof Error){
console.log(e)
}
// true
if(e instanceof InvalidArgsError){
console.log(e)
}
}