Comment construire correctement une boucle pour vous assurer que l' appel de promesse suivant et le logger.log enchaîné (res) s'exécutent de manière synchrone via l'itération? (oiseau bleu)
db.getUser(email).then(function(res) { logger.log(res); }); // this is a promise
J'ai essayé la méthode suivante (méthode de http://blog.victorquinn.com/javascript-promise- while-loop )
var Promise = require('bluebird');
var promiseWhile = function(condition, action) {
var resolver = Promise.defer();
var loop = function() {
if (!condition()) return resolver.resolve();
return Promise.cast(action())
.then(loop)
.catch(resolver.reject);
};
process.nextTick(loop);
return resolver.promise;
});
var count = 0;
promiseWhile(function() {
return count < 10;
}, function() {
return new Promise(function(resolve, reject) {
db.getUser(email)
.then(function(res) {
logger.log(res);
count++;
resolve();
});
});
}).then(function() {
console.log('all done');
});
Bien que cela semble fonctionner, mais je ne pense pas que cela garantit l'ordre d'appeler logger.log (res);
Aucune suggestion?
javascript
node.js
promise
bluebird
user2127480
la source
la source
loop
fonction est le moyen de faire des boucles synchrones). Pourquoi pensez-vous qu'il n'y a aucune garantie?while
code fonctionne?Réponses:
En fait, c'est le cas. Cette instruction est exécutée avant l'
resolve
appel.Beaucoup. Le plus important est votre utilisation de l' anti-modèle create-promise-manual - faites simplement
Deuxièmement, cette
while
fonction pourrait être beaucoup simplifiée:Troisièmement, je n'utiliserais pas une
while
boucle (avec une variable de fermeture) mais unefor
boucle:la source
action
prendvalue
comme argument danspromiseFor
. Alors je ne me laisserais pas faire une si petite modification. Merci, c'est très utile et élégant.while
boucle teste un état global alors qu'unefor
boucle a sa variable d'itération (compteur) liée au corps de la boucle lui-même. En fait, j'ai utilisé une approche plus fonctionnelle qui ressemble plus à une itération de point fixe qu'à une boucle. Vérifiez à nouveau leur code, levalue
paramètre est différent..bind()
obscurcit le nouveauvalue
, je pense que je pourrais choisir de prolonger la fonction pour plus de lisibilité. Et désolé si je suis épais, mais sipromiseFor
etpromiseWhile
ne coexistent pas, alors comment l'un appelle-t-il l'autre?return …
parreturn Promise.resolve(…)
. Si vous avez besoin de garanties supplémentaires contrecondition
ou deaction
lancer une exception (comme lePromise.method
fournit ), enveloppez tout le corps de la fonction dans unreturn Promise.resolve().then(() => { … })
Promise.resolve().then(action).…
ouPromise.resolve(action()).…
, vous n'avez pas besoin d'encapsuler la valeur de retour dethen
Si vous voulez vraiment une
promiseWhen()
fonction générale à cette fin et à d'autres, alors faites-le par tous les moyens en utilisant les simplifications de Bergi. Cependant, en raison de la manière dont les promesses fonctionnent, passer des rappels de cette manière est généralement inutile et vous oblige à sauter à travers de petits obstacles complexes.Autant que je sache, vous essayez:
.then()
chaîne par récursivité.Défini ainsi, le problème est en fait celui discuté sous «La Collection Kerfuffle» dans Promise Anti-patterns , qui propose deux solutions simples:
Array.prototype.map()
Array.prototype.reduce()
.L'approche parallèle donnera (carrément) le problème que vous essayez d'éviter - que l'ordre des réponses est incertain. L'approche sérielle construira la
.then()
chaîne requise - plate - pas de récursivité.Appelez comme suit:
Comme vous pouvez le voir, il n'y a pas besoin de la vilaine var externe
count
ou de sacondition
fonction associée . La limite (de 10 dans la question) est entièrement déterminée par la longueur du tableauarrayOfEmailAddys
.la source
Voici comment je le fais avec l'objet standard Promise.
la source
chain = chain.then(func.bind(null, "...your params here"));
ouchain = chain.then(() => func("your params here"));
Donné
Obligatoire
Solution
la source
async
est sur le point de devenir un mot réservé en JavaScript, il peut être plus clair de renommer cette fonction ici.current
n'est pas utilisé.Il existe une nouvelle façon de résoudre ce problème et c'est en utilisant async / await.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function https://ponyfoo.com/articles/understanding-javascript-async-await
la source
La fonction suggérée par Bergi est vraiment sympa:
Je veux quand même faire un petit ajout, ce qui a du sens, lors de l'utilisation des promesses:
De cette façon, la boucle while peut être intégrée dans une chaîne de promesses et se résout avec lastValue (également si l'action () n'est jamais exécutée). Voir exemple:
la source
Je ferais quelque chose comme ça:
de cette façon, dataAll est un tableau ordonné de tous les éléments à consigner. Et l'opération de journalisation s'effectuera lorsque toutes les promesses seront faites.
la source
Utilisez async et wait (es6):
la source
la source
Que diriez-vous de celui-ci en utilisant BlueBird ?
la source
Voici une autre méthode (ES6 avec promesse std). Utilise les critères de sortie de type lodash / underscore (return === false). Notez que vous pouvez facilement ajouter une méthode exitIf () dans les options à exécuter dans doOne ().
la source
Utilisation de l'objet de promesse standard et avoir la promesse renvoyer les résultats.
la source
Commencez par prendre un tableau de promesses (tableau de promesses) et après résolvez ces tableaux de promesses en utilisant
Promise.all(promisearray)
.la source