¿Cómo construir correctamente un bucle para asegurarse de que la siguiente llamada de promesa y el logger.log (res) encadenado se ejecuten sincrónicamente a través de la iteración? (azulejo)
db.getUser(email).then(function(res) { logger.log(res); }); // this is a promise
Intenté de la siguiente manera (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');
}); 
Aunque parece funcionar, no creo que garantice el orden de llamada a logger.log (res);
¿Alguna sugerencia?
                    
                        javascript
                                node.js
                                promise
                                bluebird
                                
                    
                    
                        user2127480
fuente
                
                fuente

loopfunción es la forma de hacer bucles sincrónicos). ¿Por qué crees que no hay garantía?whilecódigo?Respuestas:
De hecho, lo hace. Esa declaración se ejecuta antes de la
resolvellamada.Un montón. El más importante es el uso del antipatrón create-promise-manualmente , solo hazlo
En segundo lugar, esa
whilefunción podría simplificarse mucho:En tercer lugar, no usaría un
whilebucle (con una variable de cierre) sino unforbucle:fuente
actiontomavaluecomo argumentopromiseFor. SO no me dejaría hacer una edición tan pequeña. Gracias, es muy útil y elegante.whilebucle prueba algún estado global mientras que unforbucle tiene su variable de iteración (contador) vinculada al cuerpo del bucle. De hecho, he usado un enfoque más funcional que se parece más a una iteración de punto fijo que a un bucle. Verifique su código nuevamente, elvalueparámetro es diferente..bind()ofusca lo nuevovalue, creo que podría optar por escribir la función para facilitar la lectura. Y lo siento si estoy siendo gordo pero sipromiseForypromiseWhileno coexistimos, ¿cómo se llama uno al otro?return …porreturn Promise.resolve(…). Si necesita salvaguardas adicionales contraconditionoactionlanzar una excepción (como laPromise.methodproporciona ), envuelva todo el cuerpo de la función en unreturn Promise.resolve().then(() => { … })Promise.resolve().then(action).…oPromise.resolve(action()).…, no es necesario ajustar el valor de retorno dethenSi realmente desea una
promiseWhen()función general para este y otros propósitos, entonces hágalo utilizando las simplificaciones de Bergi. Sin embargo, debido a la forma en que funcionan las promesas, pasar las devoluciones de llamada de esta manera generalmente es innecesario y te obliga a atravesar pequeños aros complejos.Por lo que puedo decir, lo estás intentando:
.then()cadena mediante recursividad.Así definido, el problema es en realidad el que se analiza en "The Collection Kerfuffle" en Promise Anti-patterns , que ofrece dos soluciones simples:
Array.prototype.map()Array.prototype.reduce().El enfoque paralelo le dará (directamente) el problema que está tratando de evitar: que el orden de las respuestas es incierto. El enfoque en serie construirá la
.then()cadena requerida , plana, sin recursividad.Llame de la siguiente manera:
Como puede ver, no hay necesidad de la var externa fea
counto suconditionfunción asociada . El límite (de 10 en la pregunta) está determinado completamente por la longitud de la matrizarrayOfEmailAddys.fuente
Así es como lo hago con el objeto Promise estándar.
fuente
chain = chain.then(func.bind(null, "...your params here"));ochain = chain.then(() => func("your params here"));Dado
Necesario
Solución
fuente
asyncestá a punto de convertirse en una palabra reservada en JavaScript, podría agregar claridad para cambiar el nombre de esa función aquí.currentno se usa.Hay una nueva forma de resolver esto y es usando async / await.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function https://ponyfoo.com/articles/understanding-javascript-async-await
fuente
La función sugerida por Bergi es realmente agradable:
Aún así, quiero hacer una pequeña adición, que tiene sentido, cuando uso promesas:
De esta manera, el ciclo while se puede incrustar en una cadena de promesas y se resuelve con lastValue (también si la acción () nunca se ejecuta). Ver ejemplo:
fuente
Haría algo como esto:
de esta manera, dataAll es una matriz ordenada de todos los elementos a registrar. Y la operación de registro se realizará cuando se cumplan todas las promesas.
fuente
Utilice async y await (es6):
fuente
fuente
¿Qué tal este usando BlueBird ?
fuente
Aquí hay otro método (ES6 w / std Promise). Utiliza criterios de salida de tipo lodash / subrayado (return === falso). Tenga en cuenta que puede agregar fácilmente un método exitIf () en las opciones para ejecutar en doOne ().
fuente
Usar el objeto de promesa estándar y hacer que la promesa devuelva los resultados.
fuente
Primero tome la matriz de promesas (matriz de promesas) y luego resuelva estas matrices de promesas usando
Promise.all(promisearray).fuente