web-dev-qa-db-fra.com

Erreur de renvoi dans la capture de 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: l'appel du crochet est-il utile? Il me semble que cela n’a aucun effet, puisqu’il jette simplement la même erreur que celle qui a été capturée. Je base ceci sur la façon dont un essai/capture régulier fonctionne.

65
Tyler Durden

Il n'y a aucun intérêt à une prise nue et à un lancer comme vous le montrez. Il ne fait rien d'utile sauf ajouter du code et une exécution lente. Donc, si vous voulez revenir à .catch(), il devrait y avoir quelque chose que vous voulez faire dans la .catch(), sinon vous devriez simplement supprimer complètement la .catch().

Le point habituel pour cette structure générale est lorsque vous voulez exécuter quelque chose dans la .catch() telle que consigner l'erreur ou nettoyer un état (comme des fichiers fermés), mais que vous voulez que la chaîne de promesses continue à être rejetée.

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

Dans un didacticiel, il peut s'agir simplement de montrer aux utilisateurs où ils peuvent intercepter des erreurs ou d'enseigner le concept de gestion de l'erreur, puis de le renverser.


Voici quelques-unes des raisons utiles pour capturer et retranscrire:

  1. Vous voulez enregistrez l'erreur, mais conservez la chaîne de promesse comme rejetée.
  2. Vous voulez transformer l'erreur en une autre erreur (souvent pour faciliter le traitement de l'erreur à la fin de la chaîne). Dans ce cas, vous renverriez une erreur différente.
  3. Vous voulez faire un tas de traitements avant que la chaîne de promesse ne continue (comme des ressources proches/libres) mais vous voulez que la chaîne de promesse reste rejetée.
  4. Vous voulez n endroit pour placer un point d'arrêt pour le débogueur à ce stade de la chaîne de promesse en cas d'échec.

Cependant, un simple rattrapage et le renvoi de la même erreur sans autre code dans le gestionnaire de captures ne font rien d'utile pour une exécution normale du code.

84
jfriend00

Les méthodes .then() et .catch() renvoient des promesses, et si vous lancez une exception dans l'un des gestionnaires, la promesse renvoyée est rejetée et l'exception est interceptée dans le gestionnaire de rejet suivant.

Dans le code suivant, nous lançons une exception dans la première .catch(), qui est interceptée dans la seconde .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);
});

La seconde .catch() renvoie un Promis qui est rempli, le gestionnaire .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 t'aides!

11
Philippe Sultan

Cela ressemble donc à votre question: "Dans la chaîne de promesse, que fait la méthode .catch()?"

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

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

Dans la chaîne de promesses, la méthode .then() renvoie un type de bloc de données. Ce retour du morceau complétera la promesse. Le retour réussi des données complète la promesse. Vous pouvez penser à la méthode .catch() de la même manière. .catch() va toutefois gérer les récupérations de données infructueuses. La déclaration de lancement complète la promesse. Vous verrez parfois que les développeurs utilisent .catch((err) => {console.log(err))}, qui complète également la chaîne de promesses.

4
Matt Fernandez

Il n'y a pas de différence importante si vous omettez complètement l'appel à la méthode catch.

La seule chose qu'il ajoute est une micro-tâche supplémentaire, ce qui signifie en pratique que vous remarquerez le rejet de la promesse plus tard que pour une promesse qui échoue sans la clause catch.

Le prochain extrait montre ceci:

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.

4
trincot