J'écrivais du code qui fait quelque chose qui ressemble à ceci:
function getStuffDone(param) { | function getStuffDone(param) {
var d = Q.defer(); /* or $q.defer */ | return new Promise(function(resolve, reject) {
// or = new $.Deferred() etc. | // using a promise constructor
myPromiseFn(param+1) | myPromiseFn(param+1)
.then(function(val) { /* or .done */ | .then(function(val) {
d.resolve(val); | resolve(val);
}).catch(function(err) { /* .fail */ | }).catch(function(err) {
d.reject(err); | reject(err);
}); | });
return d.promise; /* or promise() */ | });
} | }
Quelqu'un m'a dit que cela s'appelait respectivement "l' anti-motif différé " ou "l' Promise
anti-motif constructeur ", qu'est-ce qui ne va pas avec ce code et pourquoi est-il appelé un anti - motif ?
javascript
promise
q
bluebird
es6-promise
Benjamin Gruenbaum
la source
la source
getStuffDone
wrapper de fonction et simplement utiliser le littéral Promise?catch
bloc dans l'getStuffDone
emballage est-il l'anti-modèle?Promise
exemple natif, vous avez également des wrappers de fonctions inutiles pour les gestionnaires.then
et.catch
(c'est-à-dire que cela pourrait être le cas.then(resolve).catch(reject)
). Une tempête parfaite d'anti-modèles.Réponses:
L' antipattern différé (maintenant anti-modèle de construction explicite) inventé par Esailija est un anti-modèle commun qui est nouveau pour les promesses, je l'ai fait moi-même lorsque j'ai utilisé les promesses pour la première fois. Le problème avec le code ci-dessus est qu'il ne parvient pas à utiliser le fait que la chaîne de promesses.
Les promesses peuvent être enchaînées avec
.then
et vous pouvez retourner des promesses directement. Votre codegetStuffDone
peut être réécrit en:Les promesses consistent à rendre le code asynchrone plus lisible et à se comporter comme du code synchrone sans cacher ce fait. Les promesses représentent une abstraction sur la valeur d'une opération ponctuelle, elles font abstraction de la notion d'une déclaration ou d'une expression dans un langage de programmation.
Vous ne devez utiliser des objets différés que lorsque vous convertissez une API en promesses et ne pouvez pas le faire automatiquement, ou lorsque vous écrivez des fonctions d'agrégation plus faciles à exprimer de cette façon.
Citant Esailija:
la source
.defer()
API dans le constructeur de promesses plus récent (et sûr), il n'a pas (en aucun cas) déprécié la notion de construction de promesses :)Qu'est ce qui ne va pas avec ça?
Quel chanceux êtes-vous. Malheureusement, ce n'est probablement pas le cas, car vous avez probablement oublié un cas de bord. Dans plus de la moitié des cas que j'ai vus, l'auteur a oublié de prendre soin du gestionnaire d'erreurs:
Si l'autre promesse est rejetée, cela se passera inaperçu au lieu d'être propagé à la nouvelle promesse (où elle serait gérée) - et la nouvelle promesse reste à jamais en attente, ce qui peut provoquer des fuites.
La même chose se produit dans le cas où votre code de rappel provoque une erreur - par exemple quand
result
n'a pas deproperty
et une exception est levée. Cela ne serait pas géré et laisserait la nouvelle promesse non résolue.En revanche, l'utilisation
.then()
prend automatiquement en charge ces deux scénarios et rejette la nouvelle promesse lorsqu'une erreur se produit:L'antipattern différé est non seulement encombrant, mais également sujet aux erreurs . L'utilisation
.then()
pour le chaînage est beaucoup plus sûre.Vraiment? Bien. Cependant, cela sera assez détaillé et copieux, surtout si vous utilisez une bibliothèque de promesses qui prend en charge d'autres fonctionnalités telles que l'annulation ou la transmission de messages. Ou peut-être le sera-t-il à l'avenir, ou vous voulez échanger votre bibliothèque contre une meilleure? Vous ne voudrez pas réécrire votre code pour cela.
Les méthodes des bibliothèques (
then
) ne supportent pas seulement nativement toutes les fonctionnalités, elles peuvent également avoir certaines optimisations en place. Leur utilisation rendra probablement votre code plus rapide, ou du moins permettra d'être optimisé par les futures révisions de la bibliothèque.Comment l'éviter?
Donc, chaque fois que vous vous trouvez à créer manuellement une
Promise
ouDeferred
des promesses déjà existantes, vérifiez d'abord l'API de la bibliothèque . L'antipattern différé est souvent appliqué par les personnes qui voient les promesses [uniquement] comme un modèle d'observation - mais les promesses sont plus que des rappels : elles sont censées être composables. Chaque bibliothèque décente a beaucoup de fonctions faciles à utiliser pour la composition des promesses de toutes les manières imaginables, en prenant soin de toutes les choses de bas niveau que vous ne voulez pas traiter.Si vous avez trouvé un besoin de composer certaines promesses d'une manière nouvelle qui n'est pas prise en charge par une fonction d'assistance existante, l'écriture de votre propre fonction avec des différés inévitables devrait être votre dernière option. Pensez à passer à une bibliothèque plus fonctionnelle et / ou à déposer un bogue sur votre bibliothèque actuelle. Son responsable doit être en mesure de dériver la composition des fonctions existantes, d'implémenter une nouvelle fonction d'assistance pour vous et / ou d'aider à identifier les cas limites qui doivent être traités.
la source
setTimeout
, où le constructeur pourrait être utilisé sans être considéré comme "Promise constructor anitpattern"?setTimeout
", mais " la fonctionsetTimeout
elle-même ".setTimeout
", mais" la fonctionsetTimeout
elle-même "" Peut décrire, relier aux différences, entre les deux?setTimeout
est clairement différente de la fonctionsetTimeout
elle - même , n'est-ce pas?