J'ai jeté un œil à la promesse de bluebird FAQ , dans laquelle il est mentionné que .then(success, fail)
est un antipattern . Je ne comprends pas très bien son explication quant à l’essai et à la capture. 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 correctement.
some_promise_call()
.then(function(res) { logger.log(res) })
.catch(function(err) { logger.log(err) })
Quelle est la différence?
Quelle est la différence?
L'appel .then()
renverra une promesse qui sera rejetée au cas où le rappel renverrait une erreur. Cela signifie que lorsque votre succès logger
échoue, l'erreur est transmise au rappel .catch()
suivant, mais pas au rappel fail
qui accompagne success
.
Voici un diagramme flux de contrôle:
Pour l'exprimer en code synchrone:
// some_promise_call().then(logger.log, logger.log)
then: {
try {
var results = some_call();
} catch(e) {
logger.log(e);
break then;
} // else
logger.log(results);
}
La seconde log
(qui ressemble au premier argument de .then()
) ne sera exécutée que dans le cas où aucune exception ne se produirait. Le bloc libellé et l'instruction break
semblent un peu bizarres, c'est en fait ce que python a try-except-else
pour (lecture recommandée!).
// some_promise_call().then(logger.log).catch(logger.log)
try {
var results = some_call();
logger.log(results);
} catch(e) {
logger.log(e);
}
L'enregistreur catch
gérera également les exceptions de l'appel de l'enregistreur de succès.
Voilà pour la différence.
Je ne comprends pas très bien son explication quant à l'essayer et attraper
L'argument est que vous voulez généralement capturer les erreurs à chaque étape du traitement et que vous ne devriez pas l'utiliser dans les chaînes. On s'attend à ce que vous ne disposiez que d'un dernier gestionnaire gérant toutes les erreurs - tandis que, lorsque vous utilisez "l'antipattern", les erreurs de certains rappels ne sont pas gérées.
Cependant, ce modèle est en réalité très utile: lorsque vous voulez gérer les erreurs qui se sont produites exactement à cette étape et que vous voulez faire quelque chose entièrement différent lorsqu'aucune erreur ne s’est produite - c’est-à-dire lorsque l’erreur est irrécupérable. Soyez conscient qu'il s'agit de branchement votre flux de contrôle. Bien sûr, cela est parfois souhaité.
Quel est le problème avec ce qui suit?
some_promise_call() .then(function(res) { logger.log(res) }, function(err) { logger.log(err) })
Que vous deviez répéter votre rappel. Tu veux plutôt
some_promise_call()
.catch(function(e) {
return e; // it's OK, we'll just log it
})
.done(function(res) {
logger.log(res);
});
Vous pouvez également envisager d’utiliser .finally()
pour cela.
Les deux ne sont pas tout à fait identiques. La différence est que le premier exemple n'interceptera pas une exception émise dans votre gestionnaire success
. Ainsi, si votre méthode ne doit jamais renvoyer que des promesses résolues, comme c'est souvent le cas, vous avez besoin d'un gestionnaire de fin catch
(ou encore d'un autre then
avec un paramètre vide success
). Bien sûr, il se peut que votre gestionnaire then
ne fasse rien qui puisse potentiellement échouer. Dans ce cas, utiliser un then
à 2 paramètres pourrait convenir.
Mais je crois que l’intérêt du texte que vous avez lié est que then
est surtout utile par rapport aux rappels en raison de sa capacité à enchaîner plusieurs étapes asynchrones, et lorsque vous le faites réellement, la forme à deux paramètres de then
ne se comporte pas assez bien comme prévu, pour la raison ci-dessus. C'est particulièrement contre-intuitif lorsqu'il est utilisé en milieu de chaîne.
En tant que personne qui a fait beaucoup de choses complexes asynchrones et s'est heurtée à des virages comme celui-ci plus que je tiens à l'admettre, je recommande vraiment d'éviter cet anti-modèle et de suivre l'approche du gestionnaire séparé.
En examinant les avantages et les inconvénients des deux, nous pouvons deviner ce qui convient le mieux à la situation. Ce sont les deux principales approches pour la mise en œuvre des promesses. Les deux ont des avantages et des inconvénients
Approche de capture
some_promise_call()
.then(function(res) { logger.log(res) })
.catch(function(err) { logger.log(err) })
Avantages
Désavantages
Approche succès/erreur
some_promise_call()
.then(function success(res) { logger.log(res) },
function error(err) { logger.log(err) })
Avantages
Désavantages
catch
si vous souhaitez gérer les erreurs renvoyées par le rappel de réussite.Simple expliquer:
Dans ES2018
Lorsque la méthode catch est appelée avec l'argument onRejected, le fichier les étapes suivantes sont prises:
- Laisser la promesse être la cette valeur.
- Revenir ? Invoke (promesse, "puis", "indéfini, surRejecté").
cela signifie:
promise.then(f1).catch(f2)
équivaut à
promise.then(f1).then(undefiend, f2)
Utiliser .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 pour ensuite les transmettre à une API asynchrone, puis manipuler la réponse. Vous souhaiterez peut-être repousser la réponse dans la base de données. Traiter tous ces flux de travail avec votre concept est faisable mais très difficile à gérer. La meilleure solution sera then().then().then().then().catch()
qui reçoit toutes les erreurs en une seule fois et vous permet de conserver la maintenabilité du code.