177 votes

Placement des prises AVANT et APRES puis

J'ai de la difficulté à comprendre la différence entre la mise en .catch AVANT et APRÈS alors imbriqués promesse.

Solution 1:

test1Async(10).then((res) => {
  return test2Async(22)
    .then((res) => {
      return test3Async(100);
    }).catch((err) => {
      throw "ERROR AFTER THEN";
    });
}).then((res) => {
  console.log(res);
}).catch((err) => {
  console.log(err);
});

Variante 2:

test1Async(10).then((res) => {
   return test2Async(22)
     .catch((err) => {
        throw "ERROR BEFORE THEN";
      })
      .then((res) => {
        return test3Async(100);
      });
  }).then((res) => {
    console.log(res);
  }).catch((err) => {
    console.log(err);
  });

Le comportement de chaque fonction est de test1 échouer si le nombre <0 test2 échoue si le nombre > 10 et test3 échoue si le numéro n'est pas 100. Dans ce cas, test2 est seulement pas.

J'ai essayé d'exécuter et de faire test2Async l'échec, à la fois AVANT et APRÈS, puis se comporte de la même façon et ce n'est pas l'exécution de la test3Async. Quelqu'un peut-il m'expliquer la différence principale pour placer des captures dans des endroits différents?

Dans chaque fonction que j' console.log('Running test X') afin de vérifier s'il est exécuté.

Cette question se pose parce que le thread précédent, j'ai posté la Façon de tourner imbriquée rappel dans la promesse?. Je me dis qu'il est un autre problème et la peine de poster un autre sujet.

373voto

jfriend00 Points 152127

Donc, en gros vous demandez quelle est la différence entre ces deux (où p est une promesse créés à partir de certaines de code précédent):

return p.then(...).catch(...);

et

return p.catch(...).then(...);

Il y a des différences quand p résout ou rejette, mais de savoir si ces différences de matière ou non dépend de ce que le code à l'intérieur de l' .then() ou .catch() des gestionnaires.

Ce qui se passe lors de l' p décide:

Dans le premier schéma, lorsque p se résout, l' .then() gestionnaire est appelé. Si c' .then() gestionnaire renvoie une valeur ou une autre promesse qui décide finalement de, puis l' .catch() gestionnaire est ignorée. Mais, si l' .then() gestionnaire soit jetés ou retourne une promesse que finalement rejette, puis l' .catch() gestionnaire d'exécuter pour la rejeter dans la promesse d'origine p, mais aussi une erreur qui se produit dans l' .then() gestionnaire.

Dans le deuxième schéma, lorsque p se résout, l' .then() gestionnaire est appelé. Si c' .then() gestionnaire soit jetés ou retourne une promesse que finalement rejette, puis l' .catch() gestionnaire ne peut pas l'attraper parce que c'est avant dans la chaîne.

Donc, c'est la différence #1. Si l' .catch() gestionnaire est APRÈS, alors il peut aussi détecter les erreurs à l'intérieur de l' .then() gestionnaire.

Ce qui se passe lors de l' p dénonce:

Maintenant, dans le premier schéma, si la promesse p rejette, puis l' .then() gestionnaire est ignorée et l' .catch() gestionnaire sera appelé comme vous le souhaitez. Ce que vous faites dans l' .catch() gestionnaire détermine ce qui est retournée comme résultat final. Si vous il suffit de retourner une valeur à partir de l' .catch() gestionnaire ou le retour d'une promesse qui décide finalement de, alors, la promesse de la chaîne d'interrupteurs à l'état résolu parce que vous "manipulé" l'erreur et retourné normalement. Si vous jeter ou de retour le refus de la promesse dans l' .catch() gestionnaire, puis le retour de la promesse reste rejeté.

Dans le deuxième schéma, si la promesse p rejette, puis l' .catch() gestionnaire est appelé. Si vous retournez une valeur normale ou une promesse qui décide finalement de l' .catch() gestionnaire (et donc de "manipulation" de l'erreur), alors, la promesse de la chaîne d'interrupteurs à l'état résolu et l' .then() gestionnaire après l' .catch() sera appelée.

De sorte que la différence #2. Si l' .catch() gestionnaire d'AVANT, alors qu'il peut gérer l'erreur et permettre l' .then() gestionnaire de toujours appelée.

Quand à utiliser:

Utilisez le premier régime si vous voulez juste un .catch() gestionnaire qui peut attraper des erreurs soit dans la promesse p ou dans l' .then() gestionnaire et un rejet de p devriez sauter .then() gestionnaire.

Utiliser le deuxième régime si vous voulez être en mesure de repérer les erreurs dans la promesse d'origine p et peut-être (en fonction des conditions), permettre la promesse de la chaîne de continuer comme résolu, donc l'exécution de l' .then() gestionnaire.

L'autre option

Il y a une autre option pour utiliser à la fois des rappels que vous pouvez passer à l' .then() comme dans:

 p.then(fn1, fn2)

Cela garantit que seul l'un d' fn1 ou fn2 ne sera jamais appelé. Si p résolu, alors fn1 sera appelée. Si p rejette, alors fn2 sera appelée. Pas de changement de résultat en fn1 peut jamais faire l' fn2 appelée ou vice versa. Donc, si vous voulez être absolument sûr que seul l'un de vos deux maîtres-chiens est appelée, peu importe ce qui se passe dans les gestionnaires eux-mêmes, alors vous pouvez utiliser p.then(fn1, fn2).

47voto

akivajgordon Points 4604

jfriend00 de réponse est excellent, mais j'ai pensé que ce serait une bonne idée d'ajouter l'analogue du code synchrone.

return p.then(...).catch(...);

est similaire à la façon synchrone:

try {
  iMightThrow() // like `p`
  then()
} catch (err) {
  handleCatch()
}

Si iMightThrow() ne pas jeter, then() sera appelée. Si elle ne jeter (ou si then() jette lui-même), alors handleCatch() sera appelée. Remarquez comment l' catch bloc n'a aucun contrôle quant à savoir si ou non then est appelé.

D'autre part,

return p.catch(...).then(...);

est similaire à la façon synchrone:

try {
  iMightThrow()
} catch (err) {
  handleCatch()
}

then()

Dans ce cas, si iMightThrow() ne pas jeter, alors then() à exécuter. Si elle ne le jeter, alors il serait à l' handleCatch() de décider si then() est appelé, parce que si handleCatch() renvoie, alors then() ne sera pas appelé, depuis l'exception sera levée à l'appelant immédiatement. Si handleCatch() peut traiter le problème, then() sera appelée.

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