0

我有这个代码。我想遍历数据库中的所有用户,并为每个用户获取他们的投资组合列表(这又是股票的集合):

 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');
  });
},

我得到的结果是所有 i 索引(用户)在所有 x 索引(投资组合)之前循环。x 不应该是 i 的内循环吗?

这与 Node.JS 的工作方式有关吗?

任何帮助深表感谢。谢谢你。

4

3 回答 3

1

@PSL:让它与async.waterfall. 可能不是最优雅的解决方案,但它现在有效。

 /**
  * @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');
  },
于 2013-09-16T11:22:14.527 回答
1

getPortfolio() 很可能是一个异步操作,并且根据内部实现,它可能会将调用排队或将它们转换为 http 请求,例如这可能需要时间,当这些请求完成时,只有你的回调函数使用 x将被调用。但同时 getPortfoli() 调用将返回。这就是为什么你看到它在你所有的 i 上快速迭代,然后你的回调才开始被调用。

于 2013-09-11T15:52:42.603 回答
1

对于具有 node.js(事件驱动)和 NoSQL 数据库的 SQL 背景的用户来说,缺少JOIN's 确实令人困惑。

为您的任务考虑以下流程:

  1. 加载所有用户。
  2. 遍历用于集合关系的每个用户和记录字段(在您的情况下为用户名),通常是_id。2b。(可选)制作对象,其中键 - 将是关系字段,在您的情况下username,值 - 将是对象本身。
  3. 使用类似查询对相关集合进行另一个查询:{ _id: { $in: ids } }其中ids将是用户 _id 的数组。在您的情况下,您需要用户名列表。
  4. 遍历每个投资组合项目并将其添加到用户对象。如果 2b 做了 - 那么不需要两次迭代。
  5. 用户已完成,并且拥有投资组合数据并准备好使用。
于 2013-09-11T15:53:58.877 回答