Zeichenfolgen anstelle von Fehlern werfen

77

throwKönnen wir nicht einfach eine Fehlermeldung direkt auslösen, da wir mit dem Schlüsselwort in Javascript alles auslösen können?

Kennt jemand einen Haken daran?

Lassen Sie mich noch etwas Hintergrundwissen hinzufügen: In der JavaScript-Welt verlassen sich die Benutzer häufig auf die Parameterprüfung, anstatt den Try-Catch-Mechanismus zu verwenden. Daher ist es sinnvoll, nur schwerwiegende Fehler mit zu werfen throw. Um jedoch einige Systemfehler abfangen zu können, muss ich für meine eigenen Fehler eine andere Klasse verwenden. Anstatt eine Unterklasse von Error zu erstellen, sollte ich einfach String verwenden.

billc.cn
quelle
1
Ist es zwar möglich, aber sinnvoll? Ich würde lieber einen Fehler als eine Zeichenfolge abfangen.
Rob W
exports.login = (req, res) => {login (req) .then (({Token, Benutzer}) => {res.send (Token);}). catch (err => {if (typeof err = == 'string') {res.status (401) .send (err);} else {console.log (err); res.status (500) .send ('Etwas ist schief gelaufen');}}); } Ich gehe mit Fehlern so um, ich bin auch verwirrt, mache ich es richtig.
Md Adil

Antworten:

53

Es ist in Ordnung, alles zu werfen, was Sie möchten, aber denken Sie daran, dass, wenn der Fang außerhalb Ihres eigenen Codes liegt, möglicherweise eine vollständige Fehlerinstanz und keine einfache Zeichenfolge erwartet wird.

lanzz
quelle
8
Beispielsweise kann davon ausgegangen werden, dass die .messageEigenschaft von Erroreine Zeichenfolge ist, versuchen, eine Zeichenfolgenmethode darauf aufzurufen, und explodieren.
Mark Amery
4
Sie können , aber ich würde nicht sagen, dass es "okay" ist .
1j01
5
Dies ist eine schreckliche Idee, da es für Sie viel schwieriger sein wird, den Fehler ohne Stack-Trace zu debuggen.
Benjamin Gruenbaum
1
@BenjaminGruenbaum Wenn Sie eine Zeichenfolge in Chrome werfen, erhalten Sie eine Stapelverfolgung. ZB `function a () {wirf" Hello World "; } a (); `wird einen Stacktrace wie diesen haben:a @ main.js:4 (anonymous) @ main.js:7
doubleOrt
1
@ Stier danke, ich wusste das nicht - jetzt versuchen Sie es mit dem Debugger, der nicht in Firefox verbunden ist :)
Benjamin Gruenbaum
54

Ja, Sie können andere Werte werfen , aber es ist keine gute Praxis .

Kennt jemand einen Haken daran?

Eine Zeichenfolge ist kein Fehlerobjekt und enthält keine nützlichen Debugging-Informationen. Devtools stützen sich darauf, wie z. B. die Datei und die Zeile, in der der Fehler erstellt wurde, die Stapelverfolgung am throwSpeicherort usw., die als Eigenschaften für ErrorObjekte verfügbar sind .

Wenn Sie daran denken, einen primitiven Zeichenfolgenwert zu werfen, werfen Sie new Error("<the string>")stattdessen einen.

Bergi
quelle
10
Es ist erwähnenswert, dass die Chrome-Devtools eine Stapelverfolgung drucken, selbst wenn Sie eine Zeichenfolge werfen. Sie verlieren die .stackEigenschaft, die für eine automatisierte Fehlerbehandlung nützlich sein kann (z. B. beim Einrichten einer automatisierten Fehlerberichterstattung an einen Server, damit Sie Fehler beheben können, die in der Produktion schief gehen), aber das ist eher ein Randfall. Das tägliche manuelle Debuggen im Browser funktioniert einwandfrei, wenn Sie Zeichenfolgen werfen.
Mark Amery
19

Sie können Fehler mit Nachrichten auslösen, wissen Sie.

try {
    throw new Error("This is an error");
} catch (e) {
    alert(e.message); // This is an error
}

Aber Sie können tatsächlich Fäden werfen:

try {
    throw "This is an error";
} catch (e) {
    alert(e); // This is an error
}
MaxArt
quelle
4
Entschuldigen Sie, dass Sie die Fragen nicht klargestellt haben. Ich weiß, dass dies alles funktioniert, aber ich interessiere mich für die möglichen Probleme bei der direkten Verwendung von Strings im Gegensatz zur Verwendung eines Fehlerobjekts.
billc.cn
Ah, ok, dann schau dir einfach Ianzz 'Kommentar an. Es fasst alle Vorbehalte darin zusammen. Mein Rat ist jedoch, ErrorObjekte mit benutzerdefinierten Nachrichten zu werfen . Es erspart Ihnen die Mühe, nach dem Fehlertyp zu suchen, um "Ihre" Fehler von anderen nativ generierten Fehlern zu unterscheiden ... Es sei denn, Sie möchten dies natürlich absichtlich tun (und dann möglicherweise die ErrorObjekte erneut in den catchBereich werfen ). .
MaxArt
5

Wie andere oben erwähnt haben, müssen Sie, wenn Sie kein Fehlerobjekt werfen, Try / Catch-Blöcke haben, um diese Objekte abzufangen und angemessen zu behandeln, oder sich in einer Welt voller Verletzungen beim Debuggen befinden.

Wenn es jedoch darum geht, Fehler für nicht fehlerbehandelte Zwecke wie die Steuerung des Programmflusses auszulösen, kann dies eine hilfreiche Methode sein, um sie throwfehlerfrei zu verwenden.

Wenn Sie zur Steuerung des Programmflusses Throws verwenden, kann dies in jeder Sprache ineffizient sein, da die Laufzeit häufig viel Aufwand erfordert, um die Informationen zum Aufrufstapel abzuwickeln und die Daten so zu serialisieren, dass sie dem Benutzerbereich zur Verfügung stehen. Indem Sie die Fehlererstellung vermeiden, können Sie diesen Leistungseinbruch vermeiden. Der Schlüssel ist, dass Sie einen Handler im Aufrufstapel haben müssen, der weiß, wie man mit dieser Situation umgeht. Wenn Sie beispielsweise throw {isHardStop: true, stopCode: SOME_CODE}die Handler so gestalten, dass dies erkannt wird, können Sie möglicherweise einen Teil Ihres Codes reduzieren oder eine sauberere Syntax wählen.

Ihr Handler für diesen Leiterfall könnte wie folgt aufgebaut sein:

try { ... } catch(thr) {
    if(!thr){
       // Is not Error or Json - Handle accordingly
    } else if(thr.isHardStop){
       // Handle the stop
    } else {
       // Most likely a real error. Handle accordingly
    }
}
Timothy C. Quinn
quelle
Nein, wenn Sie den Programmfluss steuern müssen, geben Sie ihn mit einem Wert zurück, der den Programmfluss verarbeiten kann. Eine Ausnahme ist außergewöhnlich. Wenn Sie nicht wiederherstellen können und das System eine Ausnahme auslösen muss, gilt dies nicht für den Programmablauf, sondern für die Ausnahmebehandlung.
Sukima
Ich bin damit einverstanden, dass Fehler und Ausnahmen nicht für andere Zwecke als die Ausnahmebehandlung ausgelöst werden. In meinem Beispiel werfe ich jedoch nur ein Objekt und instanziiere keinen Fehler. Daher wird nur der Try / Catch-Mechanismus für eine alternative Flusssteuerung verwendet. Es sollte einen vernachlässigbaren Leistungseinbruch geben, aber die Trainingsfähigkeit ist nicht ideal. Trotzdem habe ich das noch nie selbst gemacht und würde es heutzutage wahrscheinlich nicht mehr tun. Stattdessen würde ich wahrscheinlich eine Methode wie in Erlang / Elixir verwenden, indem ich die Logik in ein Lambda einbinde, das eine Erfolgskennung und einen Ergebniswert zurückgibt.
Timothy C. Quinn
3

Obwohl Sie jede Art von Daten werfen können, die Sie möchten, ist dies beim Debuggen nicht optimal. Ein JS- ErrorObjekt enthält alle Arten von Informationen zum Fehler und eine Nachricht. Während eine Zeichenfolge nur eine Nachricht enthalten kann.

Diese zusätzlichen Informationen umfassen:

  1. Dateiname : Aus welcher Datei der Fehler ausgelöst wurde
  2. Leinenzahl : Aus welcher Zeile der Fehler geworfen wurde
  3. Stacktrace : Von welcher Funktion wurde der Fehler aufgerufen ?

Hier ist zum Beispiel ein Stacktrace von Chrome Devtools:

Geben Sie hier die Bildbeschreibung ein

Willem van der Veen
quelle