Qu'est-ce que la promesse explicite de la construction antipattern et comment puis-je l'éviter?
J'ai écrit le code qui fait quelque chose qui ressemble à:
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 ce qui est appelé la "différés antipattern" ou la "Promise
constructeur antipattern", respectivement, ce qui est mauvais à propos de ce code et pourquoi est-ce appelé antipattern?
- Puis-je confirmer que le tenir à l'écart de ce qui est (dans le contexte de la droite, pas de gauche, par exemple) retirez le
getStuffDone
fonction wrapper et il suffit d'utiliser la Promesse littérale? - ou est d'avoir la
catch
bloc dans lagetStuffDone
wrapper de la antipattern? - Au moins pour le natif
Promise
exemple vous avez aussi inutiles fonction des wrappers pour les.then
et.catch
gestionnaires (c'est à dire il pourrait juste être.then(resolve).catch(reject)
.) Une tempête parfaite de l'anti-modèles. - ce code est écrit de cette façon à des fins didactiques. J'ai écrit cette question et la réponse dans le but d'aider les personnes qui rencontrent ce problème après avoir lu beaucoup de code à la recherche de ce genre 🙂
Vous devez vous connecter pour publier un commentaire.
La différés antipattern (maintenant explicite-construction anti-modèle) inventé par Esailija est une commune de l'anti-modèle de gens qui sont nouveaux à faire des promesses, je l'ai fait moi-même quand j'ai d'abord utilisé des promesses. Le problème avec le code ci-dessus est qui ne parvient pas à utiliser le fait que des promesses de la chaîne.
Promesses pouvez enchaîner avec
.then
et vous pouvez retourner promesses directement. Votre code dansgetStuffDone
peut être réécrite comme:Promesses sont tout au sujet de faire asynchrone code plus lisible et de se comporter comme code synchrone sans cacher ce fait. Les promesses de représenter une abstraction par rapport à une valeur de l'opération d'une fois, ils abstraite de la notion de l'instruction ou de l'expression dans un langage de programmation.
Vous ne devez utiliser différés objets lorsque vous êtes la conversion d'une API de promesses et ne peut pas le faire automatiquement, ou lorsque vous écrivez des fonctions d'agrégation qui sont plus faciles exprimée de cette façon.
Citant Esailija:
.defer()
api dans la plus récente (et jeter sûr) la promesse du constructeur, il n'en a pas (en aucune façon) rendre caduque la notion de construction de promesses 🙂.defer()
API, comme vous le dites. Un mauvais coup, à mon avis, depuis un "defer
- comme' API est plus souple, et de toute évidence pour des cas d'utilisation comme la mienne. --- Mais c'est pas vraiment de problème, bien sûr. Leur propre documentation explique comment exprimerdefer()
dans les termes de la promesse du constructeur.Promise.resolve(42)
à l'intérieur degetStuffDone
de retourner de la valeur existante, ou mieux encore utiliserPromise.resolve(getStuffDone(666)).then(...).catch(...)
au lieu de simplementgetStuffDone(666).then(...)
à assurez-vous de travailler avec une Promesse, même sigetStuffDone
n'est pas coopératif assez (comme lancer uneTypeError
) - voir Vous-Ne-Sais-JS #dignes de confiance-la promesseQuel est le problème avec elle?
Vous avez de la chance. Malheureusement, il n'a probablement pas, comme vous l'avez oublié certains cas limites. Dans plus de la moitié des occurrences que j'ai vu, l'auteur a oublié de prendre soin de la gestionnaire d'erreur:
Si les autres promesse est rejetée, cela ne se passera pas inaperçu au lieu d'être propagées à la nouvelle promesse (où il serait gérés) - et de la nouvelle promesse reste éternellement en suspens, ce qui peut induire des fuites.
La même chose se produit dans le cas que votre rappel de code provoque une erreur - p. ex. lors de
result
n'ont pas deproperty
et une exception est levée. Qui irait non gérée et laisser la nouvelle promesse non résolues.En revanche, en utilisant
.then()
ne prendront automatiquement soin de ces deux scénarios, et rejette la nouvelle promesse lorsqu'une erreur se produit:Le report de la antipattern n'est pas seulement lourd, mais aussi le risque d'erreur de. À l'aide de
.then()
pour le chaînage est beaucoup plus sûr.Vraiment? Bon. Cependant, cela va être très détaillée et copieux, surtout si vous utilisez une promesse bibliothèque qui prend en charge d'autres fonctions comme l'annulation ou de la transmission de message. Ou peut-être il sera, dans l'avenir, ou vous voulez échanger votre bibliothèque contre une meilleure? Vous ne voulez pas de reprendre ton code pour que.
Les bibliothèques méthodes (
then
) ne sont pas seulement nativement en charge toutes les fonctionnalités, ils peuvent aussi disposer de certaines optimisations en place. L'aide est susceptible de rendre votre code plus rapide, ou au moins permettre d'être optimisé par de futures révisions de la bibliothèque.Comment puis-je l'éviter?
Donc à chaque fois que vous vous trouvez création manuelle d'un
Promise
ouDeferred
et déjà les promesses sont impliqués, vérification de la bibliothèque de l'API première. Le report de la antipattern est souvent appliquée par des gens qui voient des promesses [seulement] comme un modèle observateur - mais les promesses sont en savoir plus que les rappels: ils sont censés être composable. Chaque décent bibliothèque a beaucoup de facile-à-utiliser des fonctions pour la composition de promesses dans tous les pensable manière, en prenant soin de tout le bas niveau des choses que vous ne voulez pas avoir affaire avec.Si vous avez trouvé un besoin pour composer certaines promesses d'une nouvelle manière qui n'est pas pris en charge par une fonction d'assistance, d'écrire votre propre fonction inévitables Deferreds devrait être votre dernière option. Envisager de passer à un plus plein de fonctionnalités de la bibliothèque, et/ou de soumettre un rapport de bogue à l'encontre de votre bibliothèque. Son responsable doit être en mesure de déduire la composition de fonctions existantes, de mettre en œuvre une nouvelle fonction d'aide pour vous et/ou de les aider à identifier les cas limites qui doivent être traitées.
setTimeout
, où le constructeur pourrait être utilisé, mais ne pas être considéré comme "Promesse constructeur anitpattern" ?setTimeout
", mais que "la fonctionsetTimeout
lui-même".setTimeout
", mais "la fonctionsetTimeout
lui-même"" Peut décrire , de les lier à des différences entre les deux ?setTimeout
est clairement différent de la fonctionsetTimeout
lui-même, n'est-ce pas?function () {setTimeout(dostuff, duration)}
,setTimeout(dostuff, duration)
? Peut décrire le contexte de la différence entre les deux , si au-dessus de deux variations sont , ou ne sont pas l'exacte représentation de ", appel à setTimeout est clairement différente de celle de la fonction setTimeout" ?setTimeout
fonction. VotredoStuff
devrait aller dans une promesse de rappel.Promise.prototype.done
dans la spec. Parliez-vous de la non-standard promisejs.org/api/#Promise_prototype_done, ou avez-vous direthen
?done
de Q ou jQuery ou quoi que ce soit. N'a pas vraiment d'importance, puisque son de l'anti-exemple de toute façon, mais je vais le remplacer par le standard (étant donné que j'utilise aussi la promesse du constructeur il y a)