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?
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.
function fetchUserDetails(arr) {
return arr.reduce(function(promise, email) {
return promise.then(function() {
return db.getUser(email).done(function(res) {
logger.log(res);
});
});
}, Promise.resolve());
}
Call as follows :
//Compose here, by whatever means, an array of email addresses.
var arrayOfEmailAddys = [...];
fetchUserDetails(arrayOfEmailAddys).then(function() {
console.log('all done');
});
As you can see, there's no need for the ugly outer var count
or it's associated condition
function. The limit (of 10 in the question) is determined entirely by the length of the array arrayOfEmailAddys
.