Wie kann eine Schleife korrekt erstellt werden, um sicherzustellen, dass der folgende Versprechensaufruf und die verkettete logger.log (res) synchron durch die Iteration ausgeführt werden? (Drossel)
db.getUser(email).then(function(res) { logger.log(res); }); // this is a promise
Ich habe den folgenden Weg versucht (Methode von 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');
});
Es scheint zwar zu funktionieren, aber ich glaube nicht, dass es die Reihenfolge des Aufrufs von logger.log (res) garantiert ;
Irgendwelche Vorschläge?
javascript
node.js
promise
bluebird
user2127480
quelle
quelle
loop
Funktion ist der Weg, um synchrone Schleifen zu machen). Warum gibt es Ihrer Meinung nach keine Garantie?while
Code?Antworten:
Eigentlich schon. Diese Anweisung wird vor dem
resolve
Aufruf ausgeführt.Viele. Das Wichtigste ist, dass Sie das Antipattern "Versprechen versprechen" manuell verwenden - tun Sie es einfach
Zweitens
while
könnte diese Funktion stark vereinfacht werden:Drittens würde ich keine
while
Schleife (mit einer Abschlussvariablen) verwenden, sondern einefor
Schleife:quelle
action
nimmtvalue
als Argument inpromiseFor
. SO würde ich nicht so eine kleine Bearbeitung machen lassen. Danke, es ist sehr hilfreich und elegant.while
Schleife einen globalen Zustand testet, währendfor
die Iterationsvariable (Zähler) einer Schleife an den Schleifenkörper selbst gebunden ist. Tatsächlich habe ich einen funktionaleren Ansatz verwendet, der eher einer Fixpunktiteration als einer Schleife ähnelt. Überprüfen Sie den Code erneut, dervalue
Parameter ist anders..bind()
Neue verschleiert wirdvalue
, denke ich, dass ich mich dafür entscheiden könnte, die Funktion aus Gründen der Lesbarkeit zu verlängern. Und sorry , wenn ich dick ist, aber wennpromiseFor
undpromiseWhile
koexistieren nicht, dann , wie nennt man das andere?return …
durchreturn Promise.resolve(…)
. Wenn Sie zusätzliche Schutzmaßnahmen gegen eine Ausnahme benötigencondition
oder dieseaction
Promise.method
return Promise.resolve().then(() => { … })
Promise.resolve().then(action).…
oderPromise.resolve(action()).…
, Sie müssen den Rückgabewert vonthen
Wenn Sie wirklich eine allgemeine
promiseWhen()
Funktion für diesen und andere Zwecke wünschen , dann tun Sie dies auf jeden Fall mit Bergis Vereinfachungen. Aufgrund der Art und Weise, wie Versprechen funktionieren, ist das Übergeben von Rückrufen auf diese Weise im Allgemeinen nicht erforderlich und zwingt Sie, durch komplexe kleine Reifen zu springen.Soweit ich das beurteilen kann, versuchen Sie:
.then()
Kette durch Rekursion aufgebaut.Das so definierte Problem ist tatsächlich das unter "The Collection Kerfuffle" in Promise Anti-Patterns diskutierte , das zwei einfache Lösungen bietet:
Array.prototype.map()
Array.prototype.reduce()
.Der parallele Ansatz führt (direkt) zu dem Problem, das Sie vermeiden möchten - dass die Reihenfolge der Antworten ungewiss ist. Der serielle Ansatz erstellt die erforderliche
.then()
Kette - flach - ohne Rekursion.Rufen Sie wie folgt an:
Wie Sie sehen können, ist die hässliche äußere Variable
count
oder die damit verbundenecondition
Funktion nicht erforderlich . Die Grenze (von 10 in der Frage) wird vollständig durch die Länge des Arrays bestimmtarrayOfEmailAddys
.quelle
So mache ich es mit dem Standard-Promise-Objekt.
quelle
chain = chain.then(func.bind(null, "...your params here"));
oderchain = chain.then(() => func("your params here"));
Gegeben
Erforderlich
Lösung
quelle
async
es in JavaScript zu einem reservierten Wort wird, kann dies die Klarheit beim Umbenennen dieser Funktion erhöhen.current
nicht verwendet wird.Es gibt einen neuen Weg, dies zu lösen, und zwar mithilfe von async / await.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function https://ponyfoo.com/articles/understanding-javascript-async-await
quelle
Bergis vorgeschlagene Funktion ist wirklich nett:
Trotzdem möchte ich eine winzige Ergänzung machen, die Sinn macht, wenn ich Versprechen verwende:
Auf diese Weise kann die while-Schleife in eine Versprechenskette eingebettet werden und mit lastValue aufgelöst werden (auch wenn die action () nie ausgeführt wird). Siehe Beispiel:
quelle
Ich würde so etwas machen:
Auf diese Weise ist dataAll ein geordnetes Array aller zu protokollierenden Elemente. Der Protokollvorgang wird ausgeführt, wenn alle Versprechen erfüllt sind.
quelle
Verwenden Sie asynchron und warten Sie (es6):
quelle
quelle
Wie wäre es mit BlueBird ?
quelle
Hier ist eine andere Methode (ES6 mit Standardversprechen). Verwendet Exit-Kriterien vom Typ lodash / underscore (return === false). Beachten Sie, dass Sie in Optionen, die in doOne () ausgeführt werden sollen, problemlos eine exitIf () -Methode hinzufügen können.
quelle
Wenn Sie das Standardversprechenobjekt verwenden und das Versprechen haben, werden die Ergebnisse zurückgegeben.
quelle
Nehmen Sie zuerst ein Versprechen-Array (Versprechen-Array) und lösen Sie dieses Versprechen-Array anschließend mit auf
Promise.all(promisearray)
.quelle