provare {} senza cattura {} possibile in JavaScript?


114

Ho un numero di funzioni che restituiscono qualcosa o generano un errore. In una funzione principale, chiamo ciascuno di questi e vorrei restituire il valore restituito da ciascuna funzione, o passare alla seconda funzione se la prima funzione genera un errore.

Quindi in pratica quello che ho attualmente è:

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
}

Ma in realtà vorrei solo tryrestituirlo (cioè se non genera un errore). Non ho bisogno del catchblocco. Tuttavia, il codice come try {}fallisce perché manca un catch {}blocco (non utilizzato) .

Ho messo un esempio su jsFiddle .

Quindi, c'è un modo per catchrimuovere quei blocchi ottenendo lo stesso effetto?

Risposte:


4

No. Devi tenerli.

Questo in realtà ha senso poiché gli errori non dovrebbero essere ignorati silenziosamente.


16
In tal caso, quelle funzioni non dovrebbero generare errori ma restituire, ad esempio, nulle fare qualcosa del tiporeturn func1() || func2() || func3();
ThiefMaster,

53
Questa risposta è effettivamente errata, puoi avere try {}; finally {}come mostrato in stackoverflow.com/a/5764505/68210
Daniel X Moore

4
@DanielXMoore, senza catch (e) {}, l'eccezione generata da func1()impedirebbe func2()di essere tentata.
binki

66
A volte ha perfettamente senso avere una presa vuota, quindi non sono d'accordo con la tua argomentazione.
Petr Peller

8
Questa risposta è di fatto errata e fuorviante. "In realtà ha senso" dici, ma ti sbagli, ha senso solo in alcuni casi e non in altri. È un ottimo esempio di una risposta terribile che viene accettata inspiegabilmente. Ci sono molti casi in cui ha senso non avere alcun blocco di cattura, come in una asyncfunzione, a volte. Essere costretti dal linguaggio javascript a creare catchblocchi vuoti è chiaramente inutile.
YungGun

236

Un tentativo senza una clausola catch invia il suo errore al successivo catch superiore , o alla finestra, se non è stato definito alcun catch all'interno di quel try.

Se non hai un problema , un'espressione try richiede una clausola finalmente .

try {
    // whatever;
} finally {
    // always runs
}

Quindi il modo migliore sarebbe scrivere qualcosa di simile try { // whatever; } finally { try { // whatever; } finally { try { // whatever; } finally { try { // whatever; } finally { //always run}}}?
user2284570

1
Il commento sopra non risponde accuratamente a OP perché non vuole eseguire la funzione 2 se la funzione 1 ha successo.
Andrew Steitz


Grazie è quello di cui avevo bisogno :-) Sarebbe davvero fantastico se funzionasse anche senza provare {} Voglio dire: async () => {indicateWorkInProgress () await pipelineStep1 () await pipelineStep2 () ... finalmente {stopIndicator ( )}} Sarebbe chiaro che l'intera funzione è intesa ;-) Quei blocchi try sono così brutti lì ...
Lenny

35

È possibile avere un blocco catch vuoto, senza una variabile di errore, a partire da ES2019 . Questo è chiamato binding catch facoltativo ed è stato implementato in V8 v6.6, rilasciato a giugno 2018 . La funzione è disponibile dal Nodo 10 , Chrome 66 , Firefox 58 , Opera 53 e Safari 11.1 .

La sintassi è mostrata di seguito:

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

Hai ancora bisogno di un catchblocco, ma può essere vuoto e non è necessario passare alcuna variabile. Se non vuoi affatto un blocco catch, puoi usare try/ finally, ma nota che non ingerirà errori come fa un catch vuoto.

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


2
questa risposta è la più aggiornata! in termini di ordine di esecuzione, 1. tenta il tryblocco. 2. Cattura l'errore. 3. Esegue il finallyblocco. 4. Genera l'errore. È corretto?
helsont

Grazie @helsont. Per quanto riguarda l'ordine di esecuzione nel secondo esempio di codice, non sono sicuro che si possa dire se l'errore viene rilevato e rilanciato o semplicemente (probabilmente) semplicemente lanciato e non catturato in primo luogo (poiché non c'è catch). Circonda l'intero codice con un altro try/catch e sarai in grado di rilevare l' This WILL get loggederrore.
Dan Dascalescu

Sembra molto pulito ora. Grazie per la condivisione!
LeOn - Han Li

10

No, catch(o finally) è tryamico di e sempre presente come parte di try / catch .

Tuttavia, è perfettamente valido averli vuoti, come nel tuo esempio.

Nei commenti nel tuo codice di esempio ( se func1 genera un errore, prova func2 ), sembrerebbe che quello che vuoi veramente fare sia chiamare la funzione successiva all'interno del catchblocco del precedente.


1
Hai ragione. Tuttavia, se try {...}; try {...}fosse possibile un codice simile , il significato del codice potrebbe essere più chiaro (prova il primo, altrimenti prova il secondo).
pimvdb

Informazioni sulla tua modifica: nell'esempio JSFiddle, la seconda funzione restituisce qualcosa, quindi la terza funzione è davvero valutata in quel caso? Pensavo che returnun'affermazione impedisse a qualsiasi cosa di seguirla.
pimvdb

@pimvdb Scusa, non ho controllato il violino. returnfarà sì che la funzione ritorni prematuramente. Aggiornerò la mia risposta.
alex

1
Questa risposta è effettivamente errata, puoi avere try {}; finally {}come mostrato in stackoverflow.com/a/5764505/68210
Daniel X Moore

1
@DanielXMoore Certo, lo è, ma finally{}fondamentalmente è nello stesso spirito di catch{}. Aggiornerò la risposta.
alex

6

Non consiglierei di provare-finalmente senza il fermo, perché se sia il blocco try che il blocco finale lanciano errori, l'errore generato nella clausola finalmente viene ribollito e l'errore del blocco try viene ignorato, nel mio test:

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

Risultato:

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

1

Vanno insieme in ogni lingua che conosco che li ha (JavaScript, Java, C #, C ++). Non farlo.


1
Strano che la mia sia stata sottovalutata cinque anni dopo quando dice la stessa cosa delle altre risposte qui. Il mio sembra essere l'unico ad essere stato sottovalutato. Moderatori, prendete nota.
duffymo

Tcl ha un costrutto di una sola parola molto convenientecatch {my code}
MKaama


Perché? Sembra inutile, a meno che non provi / finalmente.
duffymo

1

Ho deciso di esaminare il problema presentato da una diversa angolazione.

Sono stato in grado di determinare un modo per consentire da vicino il modello di codice richiesto mentre in parte affrontava l'oggetto di errore non gestito elencato da un altro commentatore.

il codice può essere visto @ http://jsfiddle.net/Abyssoft/RC7Nw/4/

try: catch viene posizionato all'interno di un ciclo for che consente una graziosa caduta. pur essendo in grado di iterare attraverso tutte le funzioni necessarie. quando è necessaria una gestione esplicita degli errori, viene utilizzato un array di funzioni aggiuntivo. in caso di errore e l'array funzionale con i gestori degli errori l'elemento non è una funzione, l'errore viene scaricato nella console.

Per i requisiti di stackoverflow ecco il codice inline [modificato per rendere conforme a JSLint (rimuovere gli spazi iniziali per confermare), migliorare la leggibilità]

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], [], []));


1

Se vuoi che le funzioni 2 e 3 si attivino solo se si verifica un errore, perché non le metti nel blocco catch?

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

0

Credo che sia necessario utilizzare la funzione di supporto come:

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

e usalo come:

tryIt(function1, /* args if any */);
tryIt(function2, /* args if any */);


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.