Ich möchte einige Dinge in meinem JS-Code werfen und ich möchte, dass sie instanceof Error sind, aber ich möchte auch, dass sie etwas anderes sind.
In Python würde man normalerweise die Unterklasse Exception.
Was ist bei JS zu tun?
Ich möchte einige Dinge in meinem JS-Code werfen und ich möchte, dass sie instanceof Error sind, aber ich möchte auch, dass sie etwas anderes sind.
In Python würde man normalerweise die Unterklasse Exception.
Was ist bei JS zu tun?
Wie wäre es mit dieser Lösung?
Anstatt Ihre benutzerdefinierte Fehler mit zu werfen:
throw new MyError("Oops!");
Sie würden das Fehlerobjekt umhüllen (ähnlich wie ein Decorator):
throw new MyError(Error("Oops!"));
Dadurch wird sichergestellt, dass alle Attribute korrekt sind, wie z. B. der Stapel, der Dateiname, die Zeilennummer und so weiter.
Alles, was Sie dann tun müssen, ist entweder die Attribute zu kopieren oder Getter für sie zu definieren. Hier ist ein Beispiel mit Gettern (IE9):
function MyError(wrapped)
{
this.wrapped = wrapped;
this.wrapped.name = 'MyError';
}
function wrap(attr)
{
Object.defineProperty(MyError.prototype, attr, {
get: function()
{
return this.wrapped[attr];
}
});
}
MyError.prototype = Object.create(Error.prototype);
MyError.prototype.constructor = MyError;
wrap('name');
wrap('message');
wrap('stack');
wrap('fileName');
wrap('lineNumber');
wrap('columnNumber');
MyError.prototype.toString = function()
{
return this.wrapped.toString();
};
Alle anderen Antworten haben mir nicht gefallen, sie waren zu lang, zu kompliziert oder haben den Stapel nicht richtig verfolgt. Hier mein Ansatz, wenn Sie mehr benutzerdefinierte Requisiten benötigen, übergeben Sie sie an den Konstruktor und setzen sie wie Name.
class CustomError extends Error {
constructor (message) {
super(message)
// needed for CustomError instanceof Error => true
Object.setPrototypeOf(this, new.target.prototype);
// Set the name
this.name = this.constructor.name
// Maintains proper stack trace for where our error was thrown (only available on V8)
if (Error.captureStackTrace) {
Error.captureStackTrace(this, this.constructor)
}
}
}
// create own CustomError sub classes
class SubCustomError extends CustomError{}
// Tests
console.log(new SubCustomError instanceof CustomError) // true
console.log(new SubCustomError instanceof CustomError) // true
console.log(new CustomError instanceof Error) // true
console.log(new SubCustomError instanceof Error) // true
throw new SubCustomError ('test error')
Meine Lösung ist einfacher als die anderen Antworten und hat nicht die Nachteile.
Die Prototypenkette Error und alle Eigenschaften von Error werden beibehalten, ohne dass spezifische Kenntnisse über sie erforderlich sind. Es wurde in Chrome, Firefox, Node und IE11 getestet.
Die einzige Einschränkung ist ein zusätzlicher Eintrag an der Spitze des Aufrufstapels. Aber das ist leicht zu ignorieren.
Hier ist ein Beispiel mit zwei benutzerdefinierten Parametern:
function CustomError(message, param1, param2) {
var err = new Error(message);
Object.setPrototypeOf(err, CustomError.prototype);
err.param1 = param1;
err.param2 = param2;
return err;
}
CustomError.prototype = Object.create(
Error.prototype,
{name: {value: 'CustomError', enumerable: false}}
);
Beispiel für die Verwendung:
try {
throw new CustomError('Something Unexpected Happened!', 1234, 'neat');
} catch (ex) {
console.log(ex.name); //CustomError
console.log(ex.message); //Something Unexpected Happened!
console.log(ex.param1); //1234
console.log(ex.param2); //neat
console.log(ex.stack); //stacktrace
console.log(ex instanceof Error); //true
console.log(ex instanceof CustomError); //true
}
Für Umgebungen, die ein Polyfil von setPrototypeOf erfordern:
Object.setPrototypeOf = Object.setPrototypeOf || function (obj, proto) {
obj.__proto__ = proto;
return obj;
};
Im obigen Beispiel Error.apply
(auch Error.call
) bringt bei mir nichts (Firefox 3.6/Chrome 5). Ein Workaround, den ich benutze, ist:
function MyError(message, fileName, lineNumber) {
var err = new Error();
if (err.stack) {
// remove one stack level:
if (typeof(Components) != 'undefined') {
// Mozilla:
this.stack = err.stack.substring(err.stack.indexOf('\n')+1);
}
else if (typeof(chrome) != 'undefined' || typeof(process) != 'undefined') {
// Google Chrome/Node.js:
this.stack = err.stack.replace(/\n[^\n]*/,'');
}
else {
this.stack = err.stack;
}
}
this.message = message === undefined ? err.message : message;
this.fileName = fileName === undefined ? err.fileName : fileName;
this.lineNumber = lineNumber === undefined ? err.lineNumber : lineNumber;
}
MyError.prototype = new Error();
MyError.prototype.constructor = MyError;
MyError.prototype.name = 'MyError';
In Node ist es, wie andere schon gesagt haben, ganz einfach:
class DumbError extends Error {
constructor(foo = 'bar', ...params) {
super(...params);
if (Error.captureStackTrace) {
Error.captureStackTrace(this, DumbError);
}
this.name = 'DumbError';
this.foo = foo;
this.date = new Date();
}
}
try {
let x = 3;
if (x < 10) {
throw new DumbError();
}
} catch (error) {
console.log(error);
}
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.