简体   繁体   English

循环遍历所有i:node.js

[英]Looping through x after all i : node.js

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). 我得到的结果是所有i索引(用户)都在所有x索引(投资组合)之前循环通过。 Shouldn't x be an inner loop of i? x难道不是i的内在循环吗?

Is this something related to how Node.JS works? 这与Node.JS的工作方式有关吗?

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. getPortfolio()很可能是异步操作,并且取决于内部实现,它可能将调用排队或将它们转换为http请求,例如,这可能需要一些时间,当这些请求完成时,才可以使用x进行操作的回调函数将被称为。 But meanwhile getPortfoli() call will return. 但是与此同时,getPortfoli()调用将返回。 That is exactly why you see it iterating fast over all your i's, and only then you callback starts getting called. 这就是为什么您会看到遍历所有i的迭代很快,然后才开始调用回调的原因。

Lack of JOIN 's is really confusing to users who come with SQL background to node.js (event-driven) and NoSQL databases. 缺少JOIN的用户的确使那些对Node.js(事件驱动)和NoSQL数据库具有SQL背景的用户感到困惑。

Consider this flow for your task: 为您的任务考虑以下流程

  1. Load all users. 加载所有用户。
  2. Iterate through each user and record field which is used for collection relationship (username in your case), usually it is _id. 遍历用于收集关系的每个用户和记录字段(在您的情况下为用户名),通常为_id。 2b. 2b。 (Optional) make Object, where key - will be field of relationship, in your case username , and value - will be object it self. (可选)创建对象,其中键-将是关系的字段,在您的情况下为username ,值-将是其自身的对象。
  3. Make another query to related collection with similar query: { _id: { $in: ids } } where ids will be array of user _id's. 使用类似的查询对相关集合进行另一个查询: { _id: { $in: ids } }其中ids是用户_id的数组。 In your case you need list of usernames. 在您的情况下,您需要用户名列表。
  4. Iterate through each portfolio item and add it to user object. 遍历每个项目组合项并将其添加到用户对象。 If 2b did - then no need of two iterations. 如果2b做到了-则无需进行两次迭代。
  5. Users are done, and have portfolio data and ready to be used. 用户已经完成,并拥有投资组合数据并可以使用。

@PSL: Got it working with async.waterfall . @PSL:使用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');
  },

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM