I have this code. I want to loop through all Users in a database and for each user get a list of their Portfolios (which in turn is a collection of stocks):
calculatePortfolios: function(callback) {
var thisuser;
module.exports.getAllUsers(function(err, users) {
/* Loop through all users with i */
for(var i = 0; i < users.length; i++) {
console.log('i = ' + i);
console.log(users.length);
thisuser = users[i]; // Store current user.
/* Loop through all held stocks in current user's portfolio. */
module.exports.getPortfolio(thisuser.username, function(err, portfolio) {
for(var x = 0; x < portfolio.length; x++) {
console.log('x = ' + x);
var total = parseFloat((portfolio[x].held * portfolio[x].unitprice) + thisuser.cash);
console.log(total);
console.log(thisuser.username);
module.exports.updateInvestor(thisuser.username, total, function(err, result) {
console.log(thisuser.username + ' ' + total);
});
}
});
}
callback(err, 'OK');
});
},
The result I get is that all i indices (users) are looped through before all x indices (portfolios). Shouldn't x be an inner loop of i?
Is this something related to how Node.JS works?
Any help is much appreciated. Thank you.
the getPortfolio() is most likely an asynchronous operation, and depending on the internal implementation it may either queue the calls or translate them to http requests for example that may take time, when these requests are completed only then your callback function that operates with x will be called. But meanwhile getPortfoli() call will return. That is exactly why you see it iterating fast over all your i's, and only then you callback starts getting called.
Lack of JOIN
's is really confusing to users who come with SQL background to node.js (event-driven) and NoSQL databases.
Consider this flow for your task:
username
, and value - will be object it self. { _id: { $in: ids } }
where ids
will be array of user _id's. In your case you need list of usernames. @PSL: Got it working with async.waterfall
. Probably not the most elegant solution, but it works for now.
/**
* @description Calculate the value of an investor's portfolio.
* @function
*/
calculatePortfolios: function(callback) {
async.waterfall([
function(callback) {
var allUsers = [];
module.exports.getAllUsers(function(err, users) {
for(var i = 0; i < users.length; i++) {
allUsers.push(users[i]);
}
});
callback(null, allUsers);
},
function(allUsers, callback) {
var totals = [];
for(var i = 0; i < allUsers.length; i++) {
module.exports.getPortfolio(allUsers[i].username, function(err, portfolio) {
for(var x = 0; x < portfolio.length; x++) {
totals.push(parseFloat(portfolio[x].held * portfolio[x].unitprice));
}
});
}
callback(null, allUsers, totals);
},
function(allUsers, totals, callback) {
for(var i = 0; i < allUsers.length; i++) {
module.exports.updateInvestor
(allUsers[i].username, (totals[i] + allUsers[i].cash), function(err, result) {
console.log('Updated an investor!');
});
}
callback(null, 'OK');
}
]);
callback(null, 'OK');
},
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.