essayer {} sans catch {} possible en JavaScript?

114

J'ai un certain nombre de fonctions qui renvoient quelque chose ou lancent une erreur. Dans une fonction principale, j'appelle chacune d'elles, et je voudrais retourner la valeur retournée par chaque fonction, ou passer à la deuxième fonction si la première fonction génère une erreur.

Donc, fondamentalement, ce que j'ai actuellement est:

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
}

Mais en fait, j'aimerais seulement tryle renvoyer (c'est-à-dire s'il ne génère pas d'erreur). Je n'ai pas besoin du catchbloc. Cependant, le code comme try {}échoue car il manque un catch {}bloc (inutilisé) .

J'ai mis un exemple sur jsFiddle .

Alors, y a-t-il un moyen de catchsupprimer ces blocs tout en obtenant le même effet?

pimvdb
la source

Réponses:

4

Non, vous devez les garder.

Cela a du sens car les erreurs ne doivent pas du tout être ignorées en silence.

ThiefMaster
la source
16
Dans ce cas, ces fonctions ne doivent pas générer d'erreurs mais renvoyer par exemple nullet vous faites quelque chose commereturn func1() || func2() || func3();
ThiefMaster
53
Cette réponse est factuellement incorrecte, vous pouvez avoir try {}; finally {}comme indiqué dans stackoverflow.com/a/5764505/68210
Daniel X Moore
4
@DanielXMoore, sans le catch (e) {}, l'exception lancée par func1()empêcherait func2()d'être essayée.
binki
66
Il est parfois parfaitement logique d'avoir une prise vide, donc je ne suis pas d'accord avec votre argument.
Petr Peller
8
Cette réponse est factuellement incorrecte et trompeuse. «C'est vraiment logique» dites-vous, mais vous vous trompez, cela n'a de sens que dans certains cas et pas dans d'autres. C'est un excellent exemple d'une réponse terrible acceptée inexplicablement. Il existe de nombreux cas où il est logique de ne pas avoir de bloc catch, comme dans une asyncfonction, parfois. Être forcé par le langage javascript de créer des catchblocs vides est clairement inutile.
YungGun
236

Un essai sans clause catch envoie son erreur à la capture supérieure suivante , ou à la fenêtre, si aucune capture n'est définie dans cet essai.

Si vous n'avez pas de catch , une expression try nécessite une clause finally .

try {
    // whatever;
} finally {
    // always runs
}
Kennebec
la source
La meilleure façon serait donc d'écrire quelque chose comme try { // whatever; } finally { try { // whatever; } finally { try { // whatever; } finally { try { // whatever; } finally { //always run}}}?
user2284570
1
Le commentaire ci-dessus ne répond pas exactement à OP car il ne veut pas exécuter la fonction 2 si la fonction 1 réussit.
Andrew Steitz
2
Notez qu'un essai sans catch ne gâche pas les erreurs .
Dan Dascalescu
Merci, c'est ce dont j'avais besoin :-) Ce serait vraiment génial si cela fonctionne aussi sans essayer {} Je veux dire: async () => {indiqueWorkInProgress () attend pipelineStep1 () attend pipelineStep2 () ... enfin {stopIndicator ( )}} Il serait clair que toute la fonction est destinée ;-) Ces blocs d'essai sont tellement moche là-bas ...
Lenny
35

Il est possible d'avoir un bloc catch vide, sans variable d'erreur, en commençant par ES2019 . Ceci est appelé liaison de capture facultative et a été implémenté dans la version V8 v6.6, publiée en juin 2018 . La fonctionnalité est disponible depuis Node 10 , Chrome 66 , Firefox 58 , Opera 53 et Safari 11.1 .

La syntaxe est indiquée ci-dessous:

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

Vous avez toujours besoin d'un catchbloc, mais il peut être vide et vous n'avez pas besoin de passer de variable. Si vous ne voulez pas du tout de bloc catch, vous pouvez utiliser le try/ finally, mais notez qu'il n'avalera pas les erreurs comme le fait un catch vide.

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

Dan Dascalescu
la source
2
cette réponse est la plus à jour! en termes d'ordre d'exécution, 1. il tente le tryblocage. 2. Attrape l'erreur. 3. Exécute le finallybloc. 4. Lève l'erreur. Est-ce correct?
helsont
Merci @helsont. En ce qui concerne l'ordre d'exécution dans le deuxième exemple de code, je ne suis pas sûr que l'on puisse dire si l'erreur est interceptée et relancée, ou simplement (probablement) simplement lancée et non interceptée en premier lieu (car il n'y en a pas catch). Entourez tout le code d'un autre try/catch et vous serez en mesure de détecter l' This WILL get loggederreur.
Dan Dascalescu
Ça a l'air bien propre maintenant. Merci d'avoir partagé!
LeOn - Han Li
10

Non, catch(ou finally) est tryl'ami de et toujours là dans le cadre de try / catch .

Cependant, il est parfaitement valable de les avoir vides, comme dans votre exemple.

Dans les commentaires de votre exemple de code ( si func1 génère une erreur, essayez func2 ), il semblerait que ce que vous voulez vraiment faire est d'appeler la fonction suivante à l'intérieur du catchbloc de la précédente.

Alex
la source
1
Vous avez raison. Cependant, si un code semblable try {...}; try {...}était possible, la signification du code pourrait être plus claire (essayez le premier, sinon essayez le second).
pimvdb
À propos de votre modification: Dans l'exemple JSFiddle, la deuxième fonction renvoie quelque chose, la troisième fonction est-elle vraiment évaluée dans ce cas? Je pensais qu'une returndéclaration arrête quoi que ce soit après.
pimvdb
@pimvdb Désolé, je n'ai pas vérifié le violon. returnprovoquera le retour prématuré de la fonction. Je mettrai à jour ma réponse.
alex
1
Cette réponse est factuellement incorrecte, vous pouvez avoir try {}; finally {}comme indiqué dans stackoverflow.com/a/5764505/68210
Daniel X Moore
1
@DanielXMoore Bien sûr, c'est vrai, mais finally{}c'est fondamentalement dans le même esprit que catch{}. Je mettrai à jour la réponse.
alex
6

Je ne recommanderais pas try-finally sans le catch, car si le bloc try et le bloc finally lancent des erreurs, l'erreur levée dans la clause finally est remontée et l'erreur du bloc try est ignorée, dans mon propre test:

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

Résultat:

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

Ils vont ensemble dans tous les langages que je connais qui les ont (JavaScript, Java, C #, C ++). Ne fais pas ça.

duffymo
la source
1
Bizarre que la mienne ait été rejetée cinq ans plus tard quand elle dit la même chose que d'autres réponses ici. Le mien semble être le seul à avoir été critiqué. Modérateurs, veuillez prendre note.
duffymo
Tcl a une construction à un seul mot très pratiquecatch {my code}
MKaama
Pourquoi? Se sent inutile, sauf si c'est essayer / enfin.
duffymo
1

J'ai décidé de regarder le problème présenté sous un angle différent.

J'ai pu déterminer un moyen de permettre étroitement le modèle de code demandé tout en traitant en partie l'objet d'erreur non géré répertorié par un autre commentateur.

le code peut être vu @ http://jsfiddle.net/Abyssoft/RC7Nw/4/

try: catch est placé dans une boucle for permettant une chute gracieuse. tout en étant capable de parcourir toutes les fonctions nécessaires. lorsque la gestion des erreurs explicite est nécessaire, un tableau de fonctions supplémentaire est utilisé. dans le même cas d'erreur et tableau fonctionnel avec l'élément de gestionnaires d'erreur n'est pas une fonction, l'erreur est sauvegardée dans la console.

Selon les exigences de stackoverflow, voici le code en ligne [modifié pour rendre compatible JSLint (supprimer les espaces de début pour confirmer), améliorer la lisibilité]

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

user1800957
la source
1

Si vous voulez que les fonctions 2 et 3 ne se déclenchent qu'en cas d'erreur, pourquoi ne les mettez-vous pas dans le bloc catch?

function testAll() {
  try {
    return func1();
  } catch(e) {
    try {
      return func2();
    } catch(e) {
      try {
        return func3();
      } catch(e) {
        // LOG EVERYTHING FAILED
      }
    }
  }
}
Réservoir
la source
0

Je pense que vous devez utiliser une fonction d'assistance comme:

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

et utilisez-le comme:

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

Depuis ES2019, vous pouvez facilement utiliser try {}sans catch {}:

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

Pour plus d'informations, veuillez vous référer à la proposition de Michael Ficcara

JamesJGoodwin
la source
1
Non, catchc'est toujours nécessaire, c'est juste la liaison qui n'est pas requise ...
chipit24