Como construir corretamente um loop para garantir que a seguinte chamada de promessa e o logger.log (res) encadeado sejam executados de forma síncrona por meio da iteração? (pássaro azul)
db.getUser(email).then(function(res) { logger.log(res); }); // this is a promise
Tentei da seguinte maneira (método 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');
});
Embora pareça funcionar, mas não acho que garanta a ordem de chamar logger.log (res);
Alguma sugestão?
javascript
node.js
promise
bluebird
user2127480
fonte
fonte
loop
função é a maneira de fazer loops síncronos). Por que você acha que não há garantia?while
código funciona?Respostas:
Na verdade, sim. Essa instrução é executada antes da
resolve
chamada.Grande quantidade. O mais importante é o uso do antipadrão criar-promessa-manualmente - basta fazer apenas
Em segundo lugar, essa
while
função poderia ser muito simplificada:Terceiro, eu não usaria um
while
loop (com uma variável de fechamento), mas umfor
loop:fonte
action
levavalue
como argumento empromiseFor
. ASSIM, não me deixaria fazer uma edição tão pequena. Obrigado, é muito útil e elegante.while
loop testa algum estado global enquanto umfor
loop tem sua variável de iteração (contador) ligada ao próprio corpo do loop. Na verdade, usei uma abordagem mais funcional que se parece mais com uma iteração de fixpoint do que com um loop. Verifique o código novamente, ovalue
parâmetro é diferente..bind()
ofusca o novovalue
, acho que posso escolher estender a função para facilitar a leitura. E desculpe se eu estou sendo estúpido, mas se coexistirpromiseFor
epromiseWhile
não coexistir, então como um chama o outro?return …
porreturn Promise.resolve(…)
. Se você precisar de proteções adicionais contracondition
ouaction
lançar uma exceção (comoPromise.method
fornece ), envolva todo o corpo da função em umreturn Promise.resolve().then(() => { … })
Promise.resolve().then(action).…
ouPromise.resolve(action()).…
, você não precisa quebrar o valor de retorno dethen
Se você realmente deseja uma
promiseWhen()
função geral para este e outros propósitos, então faça-o, usando as simplificações de Bergi. No entanto, por causa da maneira como as promessas funcionam, passar callbacks dessa forma geralmente é desnecessário e força você a pular pequenos obstáculos complexos.Pelo que eu posso dizer, você está tentando:
.then()
cadeia por meio de recursão.Definido assim, o problema é na verdade aquele discutido em "The Collection Kerfuffle" em Promise Anti-patterns , que oferece duas soluções simples:
Array.prototype.map()
Array.prototype.reduce()
.A abordagem paralela fornecerá (de maneira direta) o problema que você está tentando evitar - que a ordem das respostas é incerta. A abordagem serial construirá a
.then()
cadeia necessária - plana - sem recursão.Ligue da seguinte forma:
Como você pode ver, não há necessidade do feio var externo
count
ou de suacondition
função associada . O limite (de 10 na questão) é determinado inteiramente pelo comprimento da matrizarrayOfEmailAddys
.fonte
Veja como faço isso com o objeto Promessa padrão.
fonte
chain = chain.then(func.bind(null, "...your params here"));
ouchain = chain.then(() => func("your params here"));
Dado
Requeridos
Solução
fonte
async
está prestes a se tornar uma palavra reservada em JavaScript, pode ser mais claro renomear essa função aqui.current
não é usado.Existe uma nova maneira de resolver isso usando async / await.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function https://ponyfoo.com/articles/understanding-javascript-async-await
fonte
A função sugerida por Bergi é muito boa:
Ainda assim, quero fazer uma pequena adição, que faz sentido, ao usar promessas:
Desta forma, o loop while pode ser embutido em uma cadeia de promessa e resolvido com lastValue (também se a ação () nunca for executada). Consultar exemplo:
fonte
Eu faria algo assim:
dessa forma, dataAll é uma matriz ordenada de todos os elementos a serem registrados. E a operação de log será executada quando todas as promessas forem cumpridas.
fonte
Use async e await (es6):
fonte
fonte
Que tal este usando BlueBird ?
fonte
Aqui está outro método (ES6 w / std Promise). Usa critérios de saída do tipo lodash / sublinhado (return === false). Observe que você pode facilmente adicionar um método exitIf () nas opções para executar em doOne ().
fonte
Usar o objeto de promessa padrão e fazer com que a promessa retorne os resultados.
fonte
Primeiro pegue o array de promessas (array de promessa) e depois resolva esse array de promessa usando
Promise.all(promisearray)
.fonte