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?
Mohsen hat eine großartige Antwort oben in ES6, die den Namen setzt, aber wenn Sie TypeScript verwenden oder wenn Sie in der Zukunft leben, wo hoffentlich diese Vorschlag für öffentliche und private Klassenfelder die Stufe 3 als Vorschlag hinter sich gelassen hat und als Teil von ECMAScript/JavaScript in die Stufe 4 aufgestiegen ist, dann sollten Sie wissen, dass diese dann nur noch ein wenig kürzer ist. In Stufe 3 beginnen die Browser mit der Implementierung von Funktionen. Wenn Ihr Browser dies unterstützt, könnte der folgende Code funktionieren. (Getestet mit dem neuen Edge-Browser v81 scheint er gut zu funktionieren). Seien Sie jedoch gewarnt, dass es sich hierbei um eine instabile Funktion handelt, die mit Vorsicht zu genießen ist, und Sie sollten immer die Browserunterstützung für instabile Funktionen überprüfen. Dieser Beitrag ist hauptsächlich für diejenigen gedacht, die in der Zukunft leben, wenn die Browser dies unterstützen. Um die Unterstützung zu überprüfen, prüfen Sie MDN y Kann ich die . Es hat derzeit 66% Unterstützung auf dem Browsermarkt, was ein Fortschritt ist, aber nicht so toll. Wenn Sie es also wirklich jetzt benutzen wollen und nicht warten wollen, benutzen Sie einen Transpiler wie Babel oder etwas wie TypScript .
class EOFError extends Error {
name="EOFError"
}
throw new EOFError("Oops errored");
Vergleichen Sie dies mit einem namenlosen Fehler, dessen Name nicht protokolliert wird, wenn er ausgelöst wird.
class NamelessEOFError extends Error {}
throw new NamelessEOFError("Oops errored");
Der Weg, um dies richtig zu tun ist, um das Ergebnis der Anwendung aus dem Konstruktor zurück, sowie die Einstellung des Prototyps in der üblichen komplizierten javascripty Weg:
function MyError() {
var tmp = Error.apply(this, arguments);
tmp.name = this.name = 'MyError'
this.stack = tmp.stack
this.message = tmp.message
return this
}
var IntermediateInheritor = function() {}
IntermediateInheritor.prototype = Error.prototype;
MyError.prototype = new IntermediateInheritor()
var myError = new MyError("message");
console.log("The message is: '"+myError.message+"'") // The message is: 'message'
console.log(myError instanceof Error) // true
console.log(myError instanceof MyError) // true
console.log(myError.toString()) // MyError: message
console.log(myError.stack) // MyError: message \n
// <stack trace ...>
Die einzigen Probleme, die sich bei dieser Vorgehensweise ergeben (ich habe sie ein wenig überarbeitet), sind folgende
stack
y message
sind nicht enthalten in MyError
yDas erste Problem könnte behoben werden, indem alle nicht aufzählbaren Fehlereigenschaften mit Hilfe des Tricks in dieser Antwort durchlaufen werden: Ist es möglich, die nicht aufzählbaren geerbten Eigenschaftsnamen eines Objekts abzurufen? , aber das wird von ie<9 nicht unterstützt. Das zweite Problem könnte durch Herausreißen dieser Zeile im Stacktrace gelöst werden, aber ich bin mir nicht sicher, wie man das sicher macht (vielleicht einfach die zweite Zeile von e.stack.toString() entfernen?)
Das Snippet zeigt alles.
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)
}
}
Meine vorgeschlagene Lösung ist die Verwendung der .name
Eigenschaft des Fehlers zur Unterscheidung zwischen den Fehlertypen anstelle von instancof
Das beantwortet die Frage nicht ganz, aber ich denke, es ist eine vernünftige Lösung, jedenfalls für einige Szenarien.
Der Vorteil, den ich gesehen habe, ist die Möglichkeit, eine instanceof CustomError
ist, dass Sie in Ihrem Versprechen-Catch-Handler eine benutzerdefinierte Behandlung vornehmen können.
Zum Beispiel:
class CustomError extends Error {/** ... **/}
axios
.post(url, payload)
.then(data => {
if (!data.loggedIn) throw CustomError("not logged in");
return data;
})
.catch(error => {
if (error instanceof CustomError) {/** custom handling of error*//}
throw error
})
Wenn es das ist, was Sie zu erreichen versuchen, sind Sie mit dem .name
aber auch Parameter:
export const ERROR_NOT_LOGGED_IN = "ERROR_NOT_LOGGED_IN";
axios
.post(url, payload)
.then(data => {
if (!data.loggedIn) throw Error("not logged in").name=ERROR_NOT_LOGGED_IN ;
return data;
})
.catch(error => {
if (error.name === ERROR_NOT_LOGGED_IN) {/** custom handling of error*//}
throw error
})
Wenn Sie sich nicht um die Leistung bei Fehlern kümmern, ist dies das Mindeste, was Sie tun können
Object.setPrototypeOf(MyError.prototype, Error.prototype)
function MyError(message) {
const error = new Error(message)
Object.setPrototypeOf(error, MyError.prototype);
return error
}
Sie können es ohne new nur MyError(message) verwenden
Durch die Änderung des Prototyps nach dem Aufruf des Konstruktors Error müssen wir den Callstack und die Meldung nicht setzen
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.