Jak poprawnie skonstruować pętlę, aby upewnić się, że następuje wywołanie obietnicy i łańcuch logger.log (res) działają synchronicznie przez iterację? (niebieski ptak)
db.getUser(email).then(function(res) { logger.log(res); }); // this is a promise
Spróbowałem w następujący sposób (metoda z 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');
});
Chociaż wydaje się, że działa, ale nie sądzę, że gwarantuje kolejność wywoływania logger.log (res);
Jakieś sugestie?
javascript
node.js
promise
bluebird
user2127480
źródło
źródło
loop
funkcją jest sposobem na wykonanie pętli synchronicznych). Jak myślisz, dlaczego nie ma żadnej gwarancji?while
działa ten kod?Odpowiedzi:
Właściwie tak. Ta instrukcja jest wykonywana przed
resolve
wywołaniem.Wiele. Najważniejsze jest, abyś używał antywzorca tworzenia-obietnicy-ręcznie - po prostu zrób tylko
Po drugie, tę
while
funkcję można bardzo uprościć:Po trzecie, nie użyłbym
while
pętli (ze zmienną zamknięcia), alefor
pętli:źródło
action
przyjmujevalue
jako argumentpromiseFor
. WIĘC nie pozwoliłby mi zrobić tak małej edycji. Dzięki, jest bardzo pomocny i elegancki.while
pętla testuje jakiś stan globalny, podczas gdyfor
pętla ma zmienną iteracyjną (licznik) przypisaną do samej treści pętli. W rzeczywistości zastosowałem bardziej funkcjonalne podejście, które bardziej przypomina iterację punktów stałych niż pętlę. Sprawdź ponownie ich kod,value
parametr jest inny..bind()
zaciemniamy nowevalue
, myślę, że mógłbym wybrać tę funkcję odręcznie, aby była czytelna. I przepraszam, jeśli jestem gruba, ale jeślipromiseFor
ipromiseWhile
nie współistnieją, to jak jedno nazywa się drugim?return …
przezreturn Promise.resolve(…)
. Jeśli potrzebujesz dodatkowych zabezpieczeń przedcondition
lubaction
wyrzucenia wyjątku (tak jakPromise.method
to zapewnia ), zawiń całą funkcję funkcji wreturn Promise.resolve().then(() => { … })
Promise.resolve().then(action).…
lubPromise.resolve(action()).…
, nie musisz zawijać wartości zwracanejthen
Jeśli naprawdę chcesz generała
promiseWhen()
funkcję do tego i innych celów, zrób to za wszelką cenę, korzystając z uproszczeń Bergi. Jednak ze względu na sposób, w jaki działają obietnice, przekazywanie wywołań zwrotnych w ten sposób jest generalnie niepotrzebne i zmusza do przeskakiwania przez skomplikowane małe obręcze.O ile wiem, próbujesz:
.then()
łańcuch poprzez rekursję.Zdefiniowany w ten sposób problem jest w rzeczywistości omawiany w „The Collection Kerfuffle” w Promise Anti-patterns , która oferuje dwa proste rozwiązania:
Array.prototype.map()
Array.prototype.reduce()
.Podejście równoległe da (bezpośrednio) problem, którego starasz się uniknąć - kolejność odpowiedzi jest niepewna. Podejście szeregowe zbuduje wymagany
.then()
łańcuch - płaski - bez rekursji.Zadzwoń w następujący sposób:
Jak widać, nie ma potrzeby stosowania brzydkiej zmiennej zewnętrznej
count
ani powiązanej z niącondition
funkcji. Limit (w pytaniu 10) jest w całości określony przez długość tablicyarrayOfEmailAddys
.źródło
Oto, jak robię to ze standardowym obiektem Promise.
źródło
chain = chain.then(func.bind(null, "...your params here"));
lubchain = chain.then(() => func("your params here"));
Dany
wymagany
Rozwiązanie
źródło
async
ma stać się słowem zastrzeżonym w JavaScript, może to zwiększyć jasność, aby zmienić nazwę tej funkcji w tym miejscu.current
nie jest używany.Jest nowy sposób rozwiązania tego problemu i jest to użycie async / await.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function https://ponyfoo.com/articles/understanding-javascript-async-await
źródło
Sugerowana funkcja Bergi jest naprawdę fajna:
Nadal chcę zrobić drobny dodatek, który ma sens przy korzystaniu z obietnic:
W ten sposób pętla while może zostać osadzona w łańcuchu obietnic i rozwiązana za pomocą lastValue (również jeśli akcja () nigdy nie zostanie uruchomiona). Zobacz przykład:
źródło
Zrobiłbym coś takiego:
w ten sposób dataAll jest uporządkowaną tablicą wszystkich elementów do zarejestrowania. Operacja dziennika zostanie wykonana, gdy wszystkie obietnice zostaną spełnione.
źródło
Użyj async i await (es6):
źródło
źródło
A co powiesz na ten z BlueBird ?
źródło
Oto inna metoda (ES6 ze standardową obietnicą). Używa kryteriów wyjścia typu lodash / underscore (return === false). Zauważ, że możesz łatwo dodać metodę exitIf () do opcji uruchamianych w doOne ().
źródło
Używanie standardowego obiektu obietnicy i zwracanie wyników przez obietnicę.
źródło
Najpierw weź tablicę obietnic (tablicę obietnic), a po rozwiązaniu tablicy obietnic za pomocą
Promise.all(promisearray)
.źródło