Enchaînés promet de ne pas passer sur le rejet
Je suis avez des problèmes pour comprendre pourquoi les rejets ne sont pas transmis par une promesse de la chaîne et je suis en espérant que quelqu'un pourra m'aider à comprendre pourquoi. Pour moi, l'attachement d'une fonctionnalité à une chaîne de promesses implique une intention que je suis en fonction de la promesse initiale d'être remplies. C'est difficile à expliquer, alors laissez-moi vous montrer un exemple de code de mon premier problème. (Remarque: cet exemple est à l'aide d'un Noeud et le report de nœud du module. J'ai testé avec Dojo 1.8.3 et avait les mêmes résultats)
var d = require("deferred");
var d1 = d();
var promise1 = d1.promise.then(
function(wins) { console.log('promise1 resolved'); return wins;},
function(err) { console.log('promise1 rejected'); return err;});
var promise2 = promise1.then(
function(wins) { console.log('promise2 resolved'); return wins;},
function(err) { console.log('promise2 rejected'); return err;});
var promise3 = promise2.then(
function(wins) { console.log('promise3 resolved'); return wins;},
function(err) { console.log('promise3 rejected'); return err;});
d1.reject(new Error());
Les résultats de l'exécution de cette opération est de cette sortie:
promise1 rejected
promise2 resolved
promise3 resolved
Bon, pour moi, ce résultat ne fait pas de sens. En joignant à cette promesse de la chaîne, chacun est alors ce qui implique l'intention qu'il sera dépend de la réussite de la résolution de la d1 et de la raison d'être transmis à la chaîne. Si la promesse de promise1 ne reçoit pas les victoires de la valeur, mais plutôt obtient un tre de la valeur dans son gestionnaire d'erreur, comment est-il possible pour la prochaine promesse de la chaîne pour avoir son succès fonction appelée? Il n'y a aucun moyen de le passer sur un ajouter de la valeur à la prochaine promesse, car il n'a pas une valeur en soi.
Une autre façon de décrire ce que je pense: Il y a trois personnes, Jean, le Gingembre, et Bob. Jean possède un widget boutique. Le gingembre est livré dans sa boutique et demande un sac de widgets de couleurs assorties. Il n'y en a pas en stock, donc il envoie une demande à son distributeur pour obtenir expédiés à lui. Dans le même temps, il donne de Gingembre une pluie case indiquant qu'il lui doit, le sac de widgets. Bob découvre le Gingembre est d'obtenir les widgets et demande à obtenir le bleu widget quand elle fait avec eux. Elle accepte et lui donne une note indiquant qu'elle ne va. Maintenant, John, le distributeur ne peut pas trouver tous les widgets dans leur alimentation et le fabricant ne fait pas d'eux non plus, de sorte qu'ils informent Jean, qui à son tour informe le Gingembre elle ne peut pas obtenir les widgets. Comment est Bob en mesure d'obtenir un bleu widget de Gingembre, quand ne pas faire elle-même?
Une troisième perspective plus réaliste que j'ai sur cette question. Dire que j'ai deux valeurs que je voulez mettre à jour une base de données. L'un dépend de l'id de l'autre, mais je ne peux pas obtenir l'id jusqu'à ce que j'ai déjà inséré dans une base de données et a obtenu le résultat. En plus de cela, la première insertion dépend de la requête à partir de la base de données. La base de données des appels de retour promesses que j'utilise pour la chaîne de la deux appels en une séquence.
var promise = db.query({parent_id: value});
promise.then(function(query_result) {
var first_value = {
parent_id: query_result[0].parent_id
}
var promise = db.put(first_value);
promise.then(function(first_value_result) {
var second_value = {
reference_to_first_value_id: first_value_result.id
}
var promise = db.put(second_value);
promise.then(function(second_value_result) {
values_successfully_entered();
}, function(err) { return err });
}, function(err) { return err });
}, function(err) { return err });
Maintenant, dans cette situation, si la db.échec de la requête, il ferait appel de la fonction err de la première puis. Mais alors il appelle le succès fonction de la prochaine promesse. Alors que cette promesse est attendent les résultats de la première valeur, il serait au lieu d'obtenir le message d'erreur de sa fonction du gestionnaire d'erreurs.
Donc, ma question est, pourquoi aurais-je une erreur de la remise de la fonction si je dois tester pour les erreurs de mon succès?
Désolé pour la longueur de cette. Je ne savais pas comment l'expliquer d'une autre manière.
Mise à JOUR et correction
(Note: j'ai supprimé une réponse que j'avais faite à certains commentaires. Donc, si quelqu'un a commenté sur ma réponse, leurs commentaires pourraient sembler hors de son contexte, maintenant que je l'ai enlevé. Désolé pour ce faire, j'essaie de garder cette aussi court que possible.)
Merci tout le monde qui a répondu. Je tiens d'abord à m'excuser auprès de tout le monde pour écrire ma question si mal, surtout mon pseudo code. J'ai été un peu trop agressif en essayant de le garder court.
Grâce à Bergi réponse, je crois que j'ai trouvé l'erreur dans ma logique. Je pense que je pourrais avoir oublié une autre question qui a été à l'origine du problème que j'avais. C'est peut-être causer la promesse de travail à la chaîne différemment de ce que j'ai pensé qu'il devrait. Je suis toujours tester les différents éléments de mon code, donc je ne peux même pas former une bonne question pour voir ce que je fais mal encore. Je voulais vous mettre à jour tous bien et je vous remercie pour votre aide.
rejected
3 fois pour moi sur 0.10.0 et différés 0.6.3.Il fonctionne pour moi comme bien sur le nœud 0.8.3 et différés 0.6.3 gist.github.com/Stuk/694b2377057453aa6946
OriginalL'auteur Jordan | 2013-05-04
Vous devez vous connecter pour publier un commentaire.
Pas. Ce que vous décrivez n'est pas une chaîne, mais juste d'attacher tous les rappels à
d1
. Pourtant, si vous voulez à la chaîne de quelque chose avecthen
, le résultat pourpromise2
dépend de la résolution depromise1
et comment lethen
rappels manipulé.Les docs de l'état:
La
.then
méthode est généralement regardé en termes de Promesses/Un cahier des charges (ou les plus strictes Promsises/Un+ un). Cela signifie que les rappels shell retour des promesses qui seront assimilés à devenir la résolution depromise2
, et si il n'y a pas de succès/gestionnaire d'erreurs respectives résultat en cas être transmises directement àpromise2
- de sorte que vous pouvez simplement omettre le gestionnaire pour propager l'erreur.Encore, si l'erreur est traitées, la
promise2
est considérée comme fixe et sera accomplie avec cette valeur. Si vous ne voulez pas que vous auriez à re-throw
l'erreur, comme dans un try-catch clause. Sinon, vous pouvez retourner un (être)a rejeté la promesse du gestionnaire. Pas sûr de ce Dojo manière de rejeter l'est, mais:Il ne devrait pas être en mesure. Si il n'y a pas des gestionnaires d'erreur, il va tout simplement percevoir le message (((le distributeur) de Jean) de Gingembre) qu'il n'y a pas de widgets à gauche. Pourtant, si le Gingembre met en place un gestionnaire d'erreur pour ce cas, elle pourrait remplir sa promesse de donner à Bob un widget en lui donnant un vert à partir de sa propre cabane si il n'y a pas des bleues à gauche au Jean ou de son distributeur.
De traduire votre erreur rappels dans le metapher,
return err
à partir du gestionnaire serait juste envie de dire: "si il n'y a pas de widgets à gauche, juste lui donner la note qu'il n'existe pas de ceux de gauche c'est aussi bon que le widget désiré"....ce qui voudrait dire que l'erreur est gérée. Si vous ne le faites pas, omettez simplement l'erreur de rappel. Btw, votre succès rappels de ne pas
return
les promesses de la création, de sorte qu'ils semblent être tout à fait inutile. Correcte serait:ou, puisque vous n'avez pas besoin de la fermeture de l'accès valeurs de résultat de la précédente rappels, même:
Pour nettoyer @Toilal la remarque de la préféré remplacement de
throw
, estreturn $q.reject(err)
.throw
sera, je crois, encore du travail, c'est juste beaucoup plus lent.OriginalL'auteur Bergi
@Jordan, premièrement, que les commentateurs ont noté, lors de l'utilisation différée lib, votre premier exemple certainement le produit le résultat que vous attendez:
Deuxièmement, même si elle permettrait de produire le résultat que vous suggérez, il ne serait pas affecter le flux d'exécution de votre deuxième extrait, qui est un peu différente, comme:
et que, dans le cas de la première promesse d'être rejeté sera juste sortie:
Cependant (arriver à la partie la plus intéressante) même si reporté bibliothèque certainement retourne
3 x rejected
, la plupart des autres promesse bibliothèques sera de retour1 x rejected, 2 x resolved
(qui conduit à l'hypothèse que vous avez obtenu ces résultats par le biais d'une autre promesse de la bibliothèque à la place).Ce qui est en outre source de confusion, ceux d'autres bibliothèques sont plus correctes avec leur comportement. Laissez-moi vous expliquer.
Dans une synchronisation monde homologue de la "promesse de rejet" est
throw
. Donc, du point de vue sémantique, asyncdeferred.reject(new Error())
la synchronisation est égal àthrow new Error()
.Dans votre exemple, on ne jette pas des erreurs dans votre synchronisation des rappels, vous avez juste retourner, alors vous passez à la réussite de flux, avec une erreur d'une valeur de succès. Pour assurez-vous que le rejet est passé de plus, vous avez besoin de re-jeter vos erreurs:
Alors maintenant la question est, pourquoi ne différés bibliothèque pris d'erreur renvoyé comme un rejet?
Raison pour cela, c'est que le rejet en différé fonctionne un peu différent. En différé lib la règle est la suivante: promesse est rejetée lorsqu'il est résolu à l'exemple de l'erreur, de sorte que même si vous ne
deferred.resolve(new Error())
il agira en tant quedeferred.reject(new Error())
, et si vous essayez de fairedeferred.reject(notAnError)
il va lever une exception dire, que la promesse peut être rejetée seulement avec l'exemple de l'erreur. Que fait clair pourquoi l'erreur retournée parthen
rappel rejette la promesse.Il y a quelques valide le raisonnement derrière différés logique, mais c'est toujours pas sur pied d'égalité avec comment
throw
fonctionne en JavaScript, et en raison du fait que ce comportement est prévue pour le changement avec la version v0.7 de différé.Résumé court:
Pour éviter la confusion et des résultats inattendus, il suffit de suivre les règles de bonnes pratiques:
Obéissant ci-dessus, vous obtiendrez à la fois constante et les résultats attendus dans les deux différés et autres populaires promesse bibliothèques.
OriginalL'auteur Mariusz Nowak
Utiliser pouvez envelopper les erreurs à chaque niveau de la Promesse. J'ai enchaîné les erreurs dans TraceError:
Utilisation
Sortie
Fonctions
OriginalL'auteur Mathew Kurian