How to correctly construct a loop to make sure the following promise call and the chained logger.log(res) runs synchronously through iteration? (bluebird)
db.getUser(email).then(function(res) { logger.log(res); }); // this is a promise
I tried the following way (method from 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');
});
Although it seems to work, but I don't think it guarantees the order of calling logger.log(res);
Any suggestions?
Here's how I do it with the standard Promise object.
Actually, it does. That statement is executed before the
resolve
call.Lots. The most important is your use of the create-promise-manually antipattern - just do only
Second, that
while
function could be simplified a lot:Third, I would not use a
while
loop (with a closure variable) but afor
loop:There is a new way to solve this and it's by using async/await.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function https://ponyfoo.com/articles/understanding-javascript-async-await
If you really want a general
promiseWhen()
function for this and other purposes, then by all means do so, using Bergi's simplifications. However, because of the way promises work, passing callbacks in this way is generally unnecessary and forces you to jump through complex little hoops.As far as I can tell you're trying :
.then()
chain via recursion.Defined thus, the problem is actually the one discussed under "The Collection Kerfuffle" in Promise Anti-patterns, which offers two simple solutions :
Array.prototype.map()
Array.prototype.reduce()
.The parallel approach will (straightforwardly) give the issue that you are trying to avoid - that the order of the responses is uncertain. The serial approach will build the required
.then()
chain - flat - no recursion.Call as follows :
As you can see, there's no need for the ugly outer var
count
or it's associatedcondition
function. The limit (of 10 in the question) is determined entirely by the length of the arrayarrayOfEmailAddys
.Given
Required
Solution
I'd make something like this:
in this way, dataAll is an ordered array of all element to log. And log operation will perform when all promises are done.