web-dev-qa-db-fra.com

try-catch en javascript ... n'est-ce pas une bonne pratique?

Il y a une disposition pour try-catch bloquer dans javascript. Alors qu'en Java ou tout autre langage, il est obligatoire d'avoir une gestion des erreurs, je ne vois personne les utiliser en javascript plus largement. N'est-ce pas une bonne pratique ou simplement nous ne le faisons pas ' t besoin d'eux en javascript?

69
akp

Il faut éviter les erreurs throw comme moyen de contourner les conditions d'erreur dans les applications.

L'instruction throw ne doit être utilisée que "car cela ne devrait jamais se produire, planter et graver. Ne pas récupérer de façon élégante"

try catch est cependant utilisé dans une situation où les objets Host ou ECMAScript peuvent générer des erreurs.

Exemple:

var json
try {
    json = JSON.parse(input)
} catch (e) {
    // invalid json input, set to null
    json = null
}

Les recommandations de la communauté node.js sont que vous passiez des erreurs dans les rappels (car les erreurs se produisent uniquement pour les opérations asynchrones) comme premier argument

fs.readFile(uri, function (err, fileData) {
    if (err) {
        // handle
        // A. give the error to someone else
        return callback(err)
        // B. recover logic
        return recoverElegantly(err)
        // C. Crash and burn
        throw err
    }
    // success case, handle nicely
})

Il y a aussi d'autres problèmes comme try/catch est vraiment cher et c'est moche et cela ne fonctionne tout simplement pas avec les opérations asynchrones.

Ainsi, puisque les opérations synchrones ne doivent pas générer d'erreur et que cela ne fonctionne pas avec les opérations asynchrones, personne n'utilise try catch, sauf pour les erreurs générées par les objets Host ou ECMAScript.

66
Raynos

Try/catch en Javascript n'est pas aussi à l'épreuve des balles que dans d'autres langues, en raison de la nature asynchrone de Javascript. Considérez cet extrait:

try {
    setTimeout(function() {
        do_something_that_throws();
    }, 1000);
}
catch (e) {
    alert("You won't see this!");
}

Le problème est que le flux de contrôle quitte le bloc try avant que do_something_that_throws() soit exécuté, donc l'erreur renvoyée à l'intérieur du rappel n'est jamais interceptée.

Donc, try/catch est fondamentalement inapproprié dans de nombreux cas, et il n'est pas toujours évident de savoir si quelque chose exécute le code de manière asynchrone ou non. Heureusement, javascript avec son idiome particulier de rappel asynchrone à un seul thread et sa prise en charge des fermetures réelles fournit une alternative élégante: la gestion des erreurs de style passant par la continuation. Passez simplement la réponse appropriée à toute erreur en tant que fonction, par exemple:

setTimeout(function () {
    do_something_that_calls_err(function(err) {
        alert("Something went wrong, namely this: " + err);
    }),
    1000);
32
tdammers

Beaucoup de ces réponses sont un peu anciennes et ne prennent pas en compte les nouvelles fonctionnalités ES7 async et await.

En utilisant async/await, vous pouvez maintenant obtenir un flux de contrôle asynchrone comme vous le souhaitez:

async function email(address) {
  try {
    // Do something asynchronous that may throw...
    await sendEmail({ to: address, from: '[email protected]`, subject: 'Hello' })
  } catch(err) {
    if (err instanceof SomeCustomError) {
      elegantlyHandleError(err)
    } else {
      throw err
    } 
  }
})

En savoir plus sur async/await ici . Vous pouvez utiliser async/await maintenant en utilisant babel .

25
Dana Woodman

try-catch en javascript est tout aussi valide et utile que dans toute autre langue qui les implémente. Il y a une raison principale pour laquelle il n'est pas utilisé autant en javascript que dans d'autres langues. C'est la même raison pour laquelle javascript est considéré comme un langage de script laid, c'est la même raison pour laquelle les gens pensent que les programmeurs javascript ne sont pas de vrais programmeurs:

  • Javascript est un langage incroyablement accessible et omniprésent

Le simple fait que tant de personnes soient exposées au javascript (en raison de la seule langue prise en charge par les navigateurs) signifie que vous avez beaucoup de code non professionnel. Bien sûr, il existe également de nombreuses raisons mineures:

  • certaines choses en javascript sont asynchrones et ne sont donc pas catchables (trucs asynchrones)
  • il y a eu beaucoup de discussions exagérées sur la façon dont try-catch a un énorme impact sur les performances. Il a n peu de performance , mais pour la plupart du code, cela en vaut la peine.
  • javascript a été (malheureusement) implémenté d'une manière qui ignore souvent silencieusement les erreurs (changer automatiquement les chaînes en nombres par exemple)

Quoi qu'il en soit, try-catch devrait être utilisé, mais bien sûr vous devriez apprendre à les utiliser correctement - comme tout le reste dans programmation.

16
user250878

Je crois qu'une grande partie de la raison pour laquelle try..catch est rare en JavaScript car le langage a une tolérance d'erreur assez élevée. La grande majorité des situations peuvent être gérées en utilisant des vérifications de code, de bonnes valeurs par défaut et des événements asynchrones. Dans certains cas, le simple fait d'utiliser un modèle évitera les problèmes:

function Foo() {
    //this may or may not be called as a constructor!!
    //could accidentally overwrite properties on window
}

function Bar() {
    if (!(this instanceof Bar)) {
        return new Bar();
    }
    //this will only work on Bar objects, and wont impact window
}

Certains des problèmes majeurs dans d'autres langues qui provoquent des exceptions n'existent tout simplement pas dans JS. Le casting de type n'est pas nécessaire la grande majorité du temps. Au lieu de cela, la méthode préférée consiste généralement à vérifier les fonctionnalités (appliquer une interface particulière):

function doFoo(arg) {
    if (arg.foo) {
        arg.foo();
    } else {
        Bar.prototype.foo.call(arg);
    }
}

Avec l'ajout de async/await à la langue, try..catch est de plus en plus répandu. Les promesses étant la forme asynchrone de try..catch, il est logique de s'attendre à:

doSomething().then(
  doSomethingWithResult,
  doSomethingWithError
)

à la place être écrit comme:

try {
  const result = await doSomething()
  doSomethingWithResult(result)
} catch (e) {
  doSomethingWithError(e)
}
6
zzzzBov

Peut-être une autre raison pour laquelle try/catch n'est pas très utilisée en Javascript est que la construction n'était pas disponible dans les toutes premières versions de Javascript ... elle a été ajoutée plus tard.

Par conséquent, certains navigateurs plus anciens ne le prennent pas en charge. (En fait, cela peut provoquer une erreur d'analyse/syntaxe dans certains navigateurs plus anciens, ce qui est plus difficile à "programmer de manière défensive" contre que la plupart des autres types d'erreurs.)

Plus important encore, comme il n'était pas disponible au départ, les fonctions intégrées Javascript qui ont été initialement publiées (ce que l'on appellerait les fonctions de "bibliothèque" dans de nombreuses langues) ne l'utilisent pas. (Il ne fonctionne pas très bien pour "intercepter" une erreur de someobject.somefunction () s'il ne "lance" pas mais renvoie simplement "null" lorsqu'il rencontre un problème.)


Encore une autre raison possible est que le mécanisme try/catch ne semblait pas nécessaire au départ (et ne semble toujours pas très utile). Il n'est vraiment nécessaire que lorsque les appels sont systématiquement imbriqués à plusieurs niveaux; renvoyer simplement une sorte d'ERRNO fonctionnerait bien pour les appels directs (bien que pour le rendre vraiment utile chaque fois qu'il est disponible, la meilleure pratique dans la plupart des langues est de l'utiliser partout plutôt que juste pour les appels profondément imbriqués). Comme la logique Javascript devait à l'origine être petite et simple (après tout, c'est juste un complément à une page Web :-), les appels de fonction ne devaient pas être profondément imbriqués, et donc un mécanisme try/catch ne semblait pas nécessaire.

3
Chuck Kollars

Je pense qu'ils ne sont pas beaucoup utilisés car le lancement d'exceptions dans le code côté client Javascript rend plus difficile le débogage d'une page.

Plutôt que de lever des exceptions, je préfère généralement afficher une boîte d'alerte, (c'est-à-dire alert("Error, invalid...");)

Cela peut sembler étrange, mais des erreurs Javascript se produisent du côté client, si un client utilise une page que vous avez créée et que la page lève une exception, sauf si le client est un tech-savvy-coder il n'y a aucun moyen il pourra jamais vous dire quel est le problème.

Il ne vous appellera qu'en disant: "Hé, la page X ne fonctionne pas!", et ensuite ce sera à vous de trouver ce qui s'est mal passé et où dans le code.

En utilisant la boîte d'alerte à la place, il est plus probable qu'il appelle et dise quelque chose comme: "Hey, quand je clique sur le bouton A de la page X, il montre une boîte qui dit ...", croyez-moi, il sera beaucoup plus facile de trouver le bogue.

0
Marco Demaio