versuchen {} ohne catch {} in JavaScript möglich?

113

Ich habe eine Reihe von Funktionen, die entweder etwas zurückgeben oder einen Fehler auslösen. In einer Hauptfunktion rufe ich jede dieser Funktionen auf und möchte den von jeder Funktion zurückgegebenen Wert zurückgeben oder mit der zweiten Funktion fortfahren, wenn die erste Funktion einen Fehler auslöst.

Im Grunde habe ich derzeit also Folgendes:

function testAll() {
    try { return func1(); } catch(e) {}
    try { return func2(); } catch(e) {} // If func1 throws error, try func2
    try { return func3(); } catch(e) {} // If func2 throws error, try func3
}

Aber eigentlich möchte ich es nur tryzurückgeben (dh wenn es keinen Fehler auslöst). Ich brauche den catchBlock nicht. Code wie try {}schlägt jedoch fehl, weil ein (nicht verwendeter) catch {}Block fehlt .

Ich habe jsFiddle ein Beispiel gegeben .

Gibt es also eine Möglichkeit, diese catchBlöcke zu entfernen, während der gleiche Effekt erzielt wird?

pimvdb
quelle

Antworten:

4

Du musst sie behalten.

Dies ist tatsächlich sinnvoll, da Fehler überhaupt nicht stillschweigend ignoriert werden sollten.

DiebMaster
quelle
16
In diesem Fall sollten diese Funktionen keine Fehler nullreturn func1() || func2() || func3();
auslösen
52
Diese Antwort ist sachlich falsch, Sie können haben, try {}; finally {}wie in stackoverflow.com/a/5764505/68210
Daniel X Moore
4
@DanielXMoore, ohne die würde die von catch (e) {}ausgelöste Ausnahme func1()verhindern, func2()dass versucht wird.
Binki
65
Manchmal ist es vollkommen sinnvoll, einen leeren Fang zu haben, daher stimme ich Ihrem Argument nicht zu.
Petr Peller
8
Diese Antwort ist sachlich falsch und irreführend. "Es macht tatsächlich Sinn", sagen Sie, aber Sie liegen falsch, es macht nur in einigen Fällen Sinn und in anderen nicht. Es ist ein großartiges Beispiel für eine schreckliche Antwort, die unerklärlich akzeptiert wird. Es gibt viele Fälle, in denen es asyncmanchmal sinnvoll ist, keinen Catch-Block zu haben, wie in einer Funktion. Es catchist eindeutig sinnlos, von der Javascript-Sprache gezwungen zu werden, leere Blöcke zu erstellen .
YungGun
233

Ein Versuch ohne catch- Klausel sendet seinen Fehler an den nächsthöheren catch oder an das Fenster, wenn in diesem try kein catch definiert ist.

Wenn Sie keinen Haken haben , erfordert ein try-Ausdruck eine finally- Klausel.

try {
    // whatever;
} finally {
    // always runs
}
kennebec
quelle
Der beste Weg wäre also, so etwas wie zu schreiben try { // whatever; } finally { try { // whatever; } finally { try { // whatever; } finally { try { // whatever; } finally { //always run}}}?
user2284570
1
Der obige Kommentar beantwortet OP nicht genau, da er Funktion 2 nicht ausführen möchte, wenn Funktion 1 erfolgreich ist.
Andrew Steitz
2
Beachten Sie, dass ein Versuch ohne Fang keine Fehler verschluckt .
Dan Dascalescu
Danke, das habe ich gebraucht :-) Es wäre wirklich großartig, wenn es auch ohne den Versuch funktionieren würde {} Ich meine: async () => {indicWorkInProgress () warte auf PipelineStep1 () warte auf PipelineStep2 () ... endlich {stopIndicator ( )}} Es wäre klar, dass die ganze Funktion gemeint ist ;-) Diese Versuchsblöcke sind dort so hässlich ...
Lenny
35

Es ist möglich, einen leeren catch-Block ohne Fehlervariable zu haben, beginnend mit ES2019 . Dies wird als optionale Fangbindung bezeichnet und wurde in V8 v6.6 implementiert , das im Juni 2018 veröffentlicht wurde . Die Funktion ist seit Node 10 , Chrome 66 , Firefox 58 , Opera 53 und Safari 11.1 verfügbar .

Die Syntax ist unten dargestellt:

try {
  throw new Error("This won't show anything");
} catch { };

Sie benötigen noch einen catchBlock, dieser kann jedoch leer sein und Sie müssen keine Variable übergeben. Wenn Sie überhaupt keinen catch-Block möchten, können Sie das try/ verwenden finally. Beachten Sie jedoch, dass es keine Fehler verschluckt, wie dies bei einem leeren catch der Fall ist.

try {
  throw new Error("This WILL get logged");
} finally {
  console.log("This syntax does not swallow errors");
}

Dan Dascalescu
quelle
2
Diese Antwort ist die aktuellste! In Bezug auf die Ausführungsreihenfolge 1. versucht es den tryBlock. 2. Fängt den Fehler ab. 3. Führt den finallyBlock aus. 4. Wirft den Fehler. Ist das richtig?
Helsont
Danke @helsont. Was die Ausführungsreihenfolge im zweiten Codebeispiel betrifft, bin ich mir nicht sicher, ob man feststellen kann, ob der Fehler abgefangen und erneut ausgelöst wird, oder ob er (wahrscheinlich) einfach ausgelöst und überhaupt nicht abgefangen wird (da es keine gibt catch). Umgeben Sie den gesamten Code mit einem anderen try/catch und Sie können den This WILL get loggedFehler abfangen .
Dan Dascalescu
Sieht jetzt viel sauber aus. Danke für das Teilen!
LeOn - Han Li
10

Nein, catch(oder finally) ist tryein Freund und immer da als Teil von try / catch .

Es ist jedoch durchaus gültig, sie leer zu lassen, wie in Ihrem Beispiel.

In den Kommentaren in Ihrem Beispielcode ( Wenn func1 einen Fehler auslöst, versuchen Sie es mit func2 ) scheint es, dass Sie wirklich die nächste Funktion innerhalb des catchBlocks des vorherigen aufrufen möchten .

Alex
quelle
1
Du hast Recht. Wenn jedoch Code wie try {...}; try {...}möglich möglich wäre, könnte die Bedeutung des Codes klarer sein (versuchen Sie es mit dem ersten, andernfalls versuchen Sie es mit dem zweiten).
Pimvdb
Informationen zu Ihrer Bearbeitung: Im JSFiddle-Beispiel gibt die zweite Funktion etwas zurück. Wird die dritte Funktion in diesem Fall also wirklich ausgewertet? Ich dachte, eine returnAussage verhindert, dass etwas danach kommt.
Pimvdb
@pimvdb Entschuldigung, ich habe die Geige nicht überprüft. returnbewirkt, dass die Funktion vorzeitig zurückkehrt. Ich werde meine Antwort aktualisieren.
alex
1
Diese Antwort ist sachlich falsch, Sie können haben, try {}; finally {}wie in stackoverflow.com/a/5764505/68210
Daniel X Moore
1
@ DanielXMoore Sicher, es ist, aber finally{}im Grunde im gleichen Sinne wie catch{}. Ich werde die Antwort aktualisieren.
alex
6

Ich würde try-finally ohne den catch nicht empfehlen, denn wenn sowohl der try-Block als auch der finally-Block einen Fehler auslösen, wird der in der finally-Klausel ausgelöste Fehler in die Luft gesprudelt und der Fehler des try-Blocks wird in meinem eigenen Test ignoriert:

try {
  console.log('about to error, guys!');
  throw new Error('eat me!');
} finally {
  console.log ('finally, who cares');
  throw new Error('finally error');
}

Ergebnis:

>     about to error, guys!
>     finally, who cares
>     .../error.js:9
>         throw new Error('finally error');
>         ^
>     
>     Error: finally error
Joe B.
quelle
1

Sie passen in jeder Sprache zusammen, von der ich weiß, dass sie sie haben (JavaScript, Java, C #, C ++). Tu es nicht.

Duffymo
quelle
1
Seltsam, dass meine fünf Jahre später abgelehnt wurde, als sie dasselbe sagt wie andere Antworten hier. Meins scheint das einzige zu sein, das abgelehnt wurde. Moderatoren, bitte beachten Sie.
Duffymo
Tcl hat ein sehr praktisches Einzelwortkonstruktcatch {my code}
MKaama
Warum? Fühlt sich nutzlos an, es sei denn, es ist versuchen / endlich.
Duffymo
1

Ich habe beschlossen, das Problem aus einem anderen Blickwinkel zu betrachten.

Ich konnte einen Weg finden, um das angeforderte Codemuster genau zu berücksichtigen, während ich teilweise das nicht behandelte Fehlerobjekt adressierte, das von einem anderen Kommentator aufgelistet wurde.

Code kann unter http://jsfiddle.net/Abyssoft/RC7Nw/4/ eingesehen werden.

try: catch befindet sich in einer for-Schleife, die ein elegantes Durchfallen ermöglicht. während Sie in der Lage sind, alle benötigten Funktionen zu durchlaufen. Wenn eine explizite Fehlerbehandlung erforderlich ist, wird ein zusätzliches Funktionsarray verwendet. In der geraden Fehler- und Funktionsanordnung mit Fehlerbehandlungselement ist das Element keine Funktion, der Fehler wird an die Konsole ausgegeben.

Gemäß den Anforderungen des Stackoverflow ist hier der Code inline [bearbeitet, um JSLint-kompatibel zu machen (zur Bestätigung führende Leerzeichen entfernen), Lesbarkeit verbessern]

function func1() {"use strict"; throw "I don't return anything"; }
function func2() {"use strict"; return 123; }
function func3() {"use strict"; throw "I don't return anything"; }

// ctr = Code to Run <array>, values = values <array>, 
// eh = error code can be blank.
// ctr and params should match 1 <-> 1
// Data validation not done here simple POC
function testAll(ctr, values, eh) {
    "use strict";
    var cb; // cb = code block counter
    for (cb in ctr) {
        if (ctr.hasOwnProperty(cb)) {
            try {
                return ctr[cb](values[cb]);
            } catch (e) {
                if (typeof eh[cb] === "function") {
                    eh[cb](e);
                } else {
                    //error intentionally/accidentially ignored
                    console.log(e);
                }
            }
        }
    }
    return false;
}

window.alert(testAll([func1, func2, func3], [], []));

Wenn Sie

user1800957
quelle
1

Wenn Sie nur möchten, dass die Funktionen 2 und 3 ausgelöst werden, wenn ein Fehler auftritt, warum setzen Sie sie nicht in den catch-Block?

function testAll() {
  try {
    return func1();
  } catch(e) {
    try {
      return func2();
    } catch(e) {
      try {
        return func3();
      } catch(e) {
        // LOG EVERYTHING FAILED
      }
    }
  }
}
Panzer
quelle
0

Ich glaube, Sie müssen die Hilfsfunktion verwenden wie:

function tryIt(fn, ...args) {
    try {
        return fn(...args);
    } catch {}
}

und benutze es wie:

tryIt(function1, /* args if any */);
tryIt(function2, /* args if any */);
Itay Merchav
quelle
-2

Seit ES2019 können Sie problemlos verwenden try {}ohne catch {}:

try {
  parseResult = JSON.parse(potentiallyMalformedJSON);
} catch (unused) {}

Für weitere Informationen wenden Sie sich bitte an den Vorschlag von Michael Ficcara

JamesJGoodwin
quelle
1
Nein, catchist immer noch erforderlich, es ist nur die Bindung, die nicht erforderlich ist ...
chipit24