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?

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.


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
}

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


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");
}


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.


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

1

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


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


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
      }
    }
  }
}

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 */);


-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


1
Non, catchc'est toujours nécessaire, c'est juste la liaison qui n'est pas requise ...
chipit24
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.