J'ai jeté un coup d'œil à la FAQ sur la promesse bluebird , dans laquelle il mentionne que .then(success, fail)
c'est un anti-modèle . Je ne comprends pas très bien son explication quant au try and catch. Quel est le problème avec ce qui suit?
some_promise_call()
.then(function(res) { logger.log(res) }, function(err) { logger.log(err) })
Il semble que l'exemple suggère ce qui suit comme la bonne manière.
some_promise_call()
.then(function(res) { logger.log(res) })
.catch(function(err) { logger.log(err) })
Quelle est la différence?
javascript
node.js
promise
bluebird
user2127480
la source
la source
then().catch()
est plus lisible, car vous n'avez pas besoin de rechercher une virgule et d'enquêter sur ce rappel pour réussir ou échouer la branche..catch
, vous ne savez pas quelle étape a causé le problème - à l'intérieur de la dernièrethen
ou ailleurs dans la chaîne de promesse. Il a donc son propre inconvénient.some_promise_call() .then(function fulfilled(res) { logger.log(res) }, function rejected(err) { logger.log(err) })
Réponses:
L'
.then()
appel renverra une promesse qui sera rejetée au cas où le rappel génère une erreur. Cela signifie que lorsque votre succèslogger
échoue, l'erreur sera transmise au.catch()
rappel suivant , mais pas aufail
rappel associé àsuccess
.Voici un diagramme de flux de contrôle :
Pour l'exprimer en code synchrone:
Le second
log
(qui est comme le premier argument.then()
) ne sera exécuté que dans le cas où aucune exception ne se produirait. Le bloc étiqueté et l'break
instruction semblent un peu bizarres, c'est en fait ce que Python atry-except-else
pour (lecture recommandée!).L'
catch
enregistreur gérera également les exceptions de l'appel de l'enregistreur de succès.Voilà pour la différence.
L'argument est que vous souhaitez généralement détecter les erreurs à chaque étape du traitement et que vous ne devez pas l'utiliser en chaîne. On s'attend à ce que vous n'ayez qu'un seul gestionnaire final qui gère toutes les erreurs - alors que, lorsque vous utilisez le "antipattern", les erreurs dans certains des rappels ne sont pas gérées.
Cependant, ce modèle est en fait très utile: lorsque vous voulez gérer des erreurs qui se sont produites exactement à cette étape, et que vous voulez faire quelque chose de complètement différent quand aucune erreur ne s'est produite - c'est-à-dire lorsque l'erreur est irrécupérable. Sachez que cela branche votre flux de contrôle. Bien sûr, cela est parfois souhaité.
Que vous deviez répéter votre rappel. Tu veux plutôt
Vous pouvez également envisager d'utiliser
.finally()
pour cela.la source
.catch
va attraper les erreurs même dans la fonction de succès .. Personnellement, je trouve cela extrêmement mal que vous vous retrouvez avec un point d'entrée d'erreur, qui peut obtenir de multiples erreurs de plusieurs actions, mais c'est mon problème. Quoi qu'il en soit - merci pour l'info! N'avez-vous pas un outil de communication en ligne que vous êtes prêt à partager pour que je puisse demander plus de choses? : PPromise
mécanicien important sur ce site..done()
ne fait pas partie de la norme, n'est-ce pas? Au moins MDN ne répertorie pas cette méthode. Ce serait utile.done
est une chose Bluebird qui était fondamentalement obsolète parthen
+ détection de rejet non géré.Les deux ne sont pas tout à fait identiques. La différence est que le premier exemple n'attrapera pas une exception levée dans votre
success
gestionnaire. Donc, si votre méthode ne doit jamais renvoyer que des promesses résolues, comme c'est souvent le cas, vous avez besoin d'uncatch
gestionnaire de fin (ou encore d'un autrethen
avec unsuccess
paramètre vide ). Bien sûr, il se peut que votrethen
gestionnaire ne fasse rien qui puisse potentiellement échouer, auquel cas l'utilisation d'un paramètre à 2then
peut être bien.Mais je pense que le point du texte que vous avez lié est qu'il
then
est surtout utile par rapport aux rappels dans sa capacité à enchaîner un tas d'étapes asynchrones, et lorsque vous faites cela, la forme à 2 paramètres dethen
subtilement ne se comporte pas comme prévu , pour la raison ci-dessus. Il est particulièrement contre-intuitif lorsqu'il est utilisé à mi-chaîne.En tant que personne qui a fait beaucoup de trucs asynchrones complexes et qui s'est cogné dans des coins comme celui-ci plus que je ne veux l'admettre, je recommande vraiment d'éviter cet anti-pattern et d'adopter l'approche du gestionnaire séparé.
la source
En examinant les avantages et les inconvénients des deux, nous pouvons faire une estimation calculée de ce qui convient à la situation. Ce sont les deux principales approches de mise en œuvre des promesses. Les deux ont ses avantages et ses inconvénients
Avantages
Désavantages
Avantages
Inconvénients
catch
si vous souhaitez gérer les erreurs générées par le rappel de réussitela source
Expliquez simplement:
Dans ES2018
cela signifie:
équivaut à
la source
L'utilisation
.then().catch()
vous permet d'activer le chaînage des promesses qui est nécessaire pour exécuter un flux de travail. Vous devrez peut-être lire certaines informations de la base de données, puis vous souhaitez les transmettre à une API asynchrone, puis vous souhaitez manipuler la réponse. Vous souhaiterez peut-être repousser la réponse dans la base de données. Gérer tous ces flux de travail avec votre concept est faisable mais très difficile à gérer. La meilleure solution sera dethen().then().then().then().catch()
recevoir toutes les erreurs en une seule fois et de conserver la maintenabilité du code.la source
Utiliser
then()
etcatch()
aider à enchaîner le succès et le gestionnaire d'échec sur la promessecatch()
travaux sur promesse retournés parthen()
. Il gère,then()
ne gère pas cela.)1. let promiseRef: Promise = this. aTimetakingTask (false); 2. promiseRef 3. .then( 4. (result) => { 5. /* successfully, resolved promise. 6. Work on data here */ 7. }, 8. (error) => console.log(error) 9. ) 10. .catch( (e) => { 11. /* successfully, resolved promise. 12. Work on data here */ 13. });
Cela a du sens car la promesse renvoyée par
then()
n'a pas d'erreur si un rappel en prend soin.la source
catch
rappel semble incorrecte.Au lieu de mots, bon exemple. Code suivant (si première promesse résolue):
est identique à:
Mais avec la première promesse rejetée, ce n'est pas identique:
la source