105 votes

Erreur de relance dans la capture de la promesse

J'ai trouvé le code suivant dans un tutoriel :

promise.then(function(result){
    //some code
}).catch(function(error) {
    throw(error);
});

Je suis un peu confus : est-ce que l'appel à la prise accomplit quelque chose ? Il me semble qu'il n'a pas d'effet, puisqu'il lance simplement la même erreur que celle qui a été attrapée. Je me base sur le fonctionnement d'un try/catch classique.

0 votes

Pourriez-vous fournir un lien vers le tutoriel ? Peut-être y a-t-il un contexte supplémentaire qui serait utile...

0 votes

@Igor Je ne peux pas, c'est sur Pluralsight. C'est peut-être juste un espace pour une logique de gestion des erreurs ?

0 votes

C'est ce que je suppose, car il ne fait rien de plus que de transmettre l'erreur à l'appelant, ce qui pourrait également être accompli en n'ayant pas le catch pour commencer.

150voto

jfriend00 Points 152127

Il n'y a aucun intérêt à attraper et à lancer un objet nu comme vous le montrez. Il ne fait rien d'utile, sauf ajouter du code et ralentir l'exécution. Donc, si vous voulez .catch() et rethrow, il devrait y avoir quelque chose que vous voulez faire dans le fichier .catch() sinon, vous devez simplement supprimer le .catch() entièrement.

Le point habituel pour cette structure générale est lorsque vous voulez exécuter quelque chose dans la section .catch() comme enregistrer l'erreur ou nettoyer un état (comme fermer des fichiers), mais vous voulez que la chaîne de promesses continue comme elle a été rejetée.

promise.then(function(result){
    //some code
}).catch(function(error) {
    // log and rethrow 
    console.log(error);
    throw error;
});

Dans un tutoriel, il peut être là uniquement pour montrer aux gens où ils peuvent attraper les erreurs ou pour enseigner le concept de traitement de l'erreur, puis de rejet.


Voici quelques-unes des raisons utiles pour attraper et relancer :

  1. Vous voulez enregistrer l'erreur mais conservez la chaîne de promesses telle que rejetée.
  2. Vous voulez transformer l'erreur en une autre erreur (souvent pour faciliter le traitement des erreurs en fin de chaîne). Dans ce cas, il faut relancer une autre erreur.
  3. Vous voulez faire un tas de traitement avant que la chaîne de promesse continue (comme les ressources fermées/libres) mais vous voulez que la chaîne de promesses reste rejetée.
  4. Vous voulez un endroit où placer un point d'arrêt pour le débogueur à ce stade de la chaîne de promesses s'il y a un échec.
  5. Vous voulez traiter une erreur spécifique ou un ensemble d'erreurs mais renvoie les autres afin qu'ils se propagent à l'appelant.

Mais, un simple catch et rethrow de la même erreur sans autre code dans le catch handler ne fait rien d'utile pour le fonctionnement normal du code.

0 votes

A mon avis, c'est non. \t bon exemple. Avec une telle approche, vous pouvez facilement obtenir plusieurs enregistrements pour une seule erreur. En Java, vous pouvez simplement throw new Exception(periousException); Je ne sais pas si javascript supporte les erreurs imbriquées, mais de toute façon "log and throw" est une mauvaise pratique.

30 votes

@Cherry - Vous ne pouvez pas dire qu'il s'agit d'une mauvaise pratique en général. Il y a des moments où un module veut consigner ses propres erreurs à sa manière et c'est une façon de le faire. D'ailleurs, je ne recommande pas cela, j'explique simplement qu'il n'y a aucune raison d'avoir un module de type .catch() et lancera la même erreur à l'intérieur du catch, à moins que vous ne fassiez quelque chose d'autre dans la fenêtre .catch() . C'est le but de cette réponse.

0 votes

En général, les exceptions doivent correspondre au niveau d'abstraction. Il est parfaitement acceptable d'attraper une exception liée à la base de données, par exemple, et de lancer quelque chose comme une exception de "service" qui sera gérée par l'appelant. Ceci est particulièrement utile lorsque vous ne souhaitez pas exposer les détails des exceptions de bas niveau.

22voto

Philippe Sultan Points 884

Les deux sites .then() y .catch() renvoient des promesses, et si vous lancez une exception dans l'un ou l'autre des gestionnaires, la promesse renvoyée est rejetée et l'exception sera prise en compte dans le gestionnaire de rejet suivant.

Dans le code suivant, nous lançons une exception dans le premier fichier .catch() qui est pris dans la deuxième .catch() :

new Promise((resolve, reject) => {
    console.log('Initial');

    resolve();
})
.then(() => {
    throw new Error('Something failed');

    console.log('Do this'); // Never reached
})
.catch(() => {
    console.log('Something failed');
    throw new Error('Something failed again');
})
.catch((error) => {
    console.log('Final error : ', error.message);
});

Le deuxième .catch() renvoie une promesse qui se réalise, le .then() peut être appelé :

new Promise((resolve, reject) => {
    console.log('Initial');

    resolve();
})
.then(() => {
    throw new Error('Something failed');

    console.log('Do this'); // Never reached
})
.catch(() => {
    console.log('Something failed');
    throw new Error('Something failed again');
})
.catch((error) => {
    console.log('Final error : ', error.message);
})
.then(() => {
    console.log('Show this message whatever happened before');
});

Référence utile : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises#Chaining_after_a_catch

J'espère que cela vous aidera !

4voto

trincot Points 10112

Il n'y a pas de différence importante si on laisse de côté le catch complètement l'appel de la méthode.

La seule chose qu'elle ajoute est une microtâche supplémentaire, ce qui signifie en pratique que vous remarquerez le rejet de la promesse plus tard que dans le cas d'une promesse qui échoue sans la fonction catch clause.

L'extrait suivant en fait la démonstration :

var p;
// Case 1: with catch
p = Promise.reject('my error 1')
       .catch(function(error) {
          throw(error);
       });

p.catch( error => console.log(error) );
// Case 2: without catch
p = Promise.reject('my error 2');

p.catch( error => console.log(error) );

Notez comment le deuxième rejet est signalé avant le premier. C'est à peu près la seule différence.

3voto

Matt Fernandez Points 192

Donc on dirait que votre question est, "Dans la chaîne de promesse, qu'est-ce que le .catch() méthode faire ?"

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/throw

L'instruction throw "s'arrêtera (les instructions après throw ne seront pas exécutées), et le contrôle sera transmis au premier bloc catch de la pile d'appels. Si aucun bloc catch n'existe parmi les fonctions appelantes, le programme se terminera."

Dans la chaîne de promesses, le .then() retournera un certain type de données. Le retour du morceau de données complètera la promesse. Le retour réussi des données complète la promesse. Vous pouvez penser à la .catch() de la même manière. .catch() Cependant, il traitera les récupérations de données qui n'ont pas abouti. L'instruction throw termine la promesse. Occasionnellement, vous verrez des développeurs utiliser .catch((err) => {console.log(err))} ce qui compléterait également la chaîne de promesses.

0voto

Aylian Craspa Points 21

En fait, il n'est pas nécessaire de le relancer, il suffit de laisser Promise.catch vide, sinon il sera considéré comme ne gérant pas le rejet, puis d'envelopper le code dans un try catch et il attrapera automatiquement l'erreur qui passe.

try{
  promise.then(function(result){
    //some code
  }).catch(function(error) {
    //no need for re throwing or any coding. but leave this as this otherwise it will consider as un handled
  });
}catch(e){
  console.log(e);
  //error can handle in here
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X