NodeJs - 带有for循环的嵌套函数在

时间:2017-03-19 09:05:38

标签: node.js mongodb loops callback nested

今天我的问题实际上是关于由于循环不能正常工作而发生的问题,但无论如何,如果我有关于设计的问题我会很开心。



app.post('/admin/earning/:multiplier', function (req, res) {

  var multiplier = req.params.multiplier;

  var now = new Date();

  var List=[];

  var dailySaving;

  //  Getting the investors emails(key) from the collection.

  db.getInvestorsFromValidatedInvests(function(err,result){

    if(err){console.log(err);}

    console.log(result);

    List = result;

    console.log('Inside the List scope'+List[0]);

    for(var i=0;i<List.length;i++){

      db.returnTotalInvestingfromValidatedInvests(List[i],function(err,rst){

      if(err){console.log(err);}

      console.log(rst);

      var dailySaving = ((rst*multiplier)/100);

      console.log('Daily Savings which is going to be added is that  :  ' +dailySaving);

      console.log(List[i]);

      db.multiplyInvestAndAddSavings(List[i],dailySaving,function(err,rest){

        if(err){console.log(err);}

        console.log(rest);

      });

    });

    }

    });

  res.json('Going to be Prepared...');
});
&#13;
&#13;
&#13;

在这里,我将分享您的每个数据库功能:

第一个函数从db获取所有者的电子邮件并返回一个数组,然后,我想对这个数组的每个元素进行一些操作,我决定使用for循环,但它无法正常工作。

&#13;
&#13;
Db.prototype.getInvestorsFromValidatedInvests = function(callback){
  MongoClient.connect("mongodb://xxxxxxx:xxxxxxx@ds9999.mlab.com:99986/xxxxxx", function (err, db) {
    if (err) { return console.dir(err); }
    db.collection('validatedInvests').distinct("owner",function(err,result){
      if(err){console.log(err); callback(err,null);}
      callback(null,result);
    });
    db.close();
});
}
&#13;
&#13;
&#13;

&#13;
&#13;
Db.prototype.returnTotalInvestingfromValidatedInvests = function(owner,callback){
  MongoClient.connect("mongodb://xxxxxxxx:xxxxxxx@ds09999.mlab.com:9996/aslanservices", function (err, db) {
    if (err) { return console.dir(err); }
    db.collection('validatedInvests').find({"owner":owner}).toArray(function(err,result){
      var sum=0;
      if(err){console.log(err); callback(err,null);}
      for(var j=0;j<result.length;j++){
        sum+=parseInt(result[j].amount); 
      }
      callback(null,sum);
    });
    db.close();
});
}
&#13;
&#13;
&#13;

&#13;
&#13;
Db.prototype.multiplyInvestAndAddSavings = function(owner,amount,callback){
  MongoClient.connect("mongodb://xxxxxx:xxxxxxx@ds99996.mlab.com:39996/aslanservices", function (err, db) {
    if (err) { return console.dir(err); }
    console.log('Db talking amount is'+amount);
    db.collection('investClients').updateOne({"email":owner},
    {
      $inc : {
        "savingsAccount" : +amount
      },
      
    },
    {
      upsert : true
    }
    ,function(err,result){
      if(err){callback(err,null);}
      callback(null,result);
    });
    db.close();
});
}
&#13;
&#13;
&#13;

输出结果为:

列表范围内&gt;让我们说blablabla@gmail.com

220

将要添加的每日储蓄是:8.8

未定义

150

将要添加的每日储蓄是:6

未定义

Db谈话量是8.8

Db谈话量是6

预期的输出是:

220

将要添加的每日储蓄是:8.8

blablabla@gmail.com

Db谈话量是8.8

150

将要添加的每日储蓄是:6

secondblablabla@gmail.com

Db谈话量是6

1 个答案:

答案 0 :(得分:2)

问题是您正在使用内部具有异步功能的for循环。让我试着解释一下:

for(var i=0;i<List.length;i++){
    // first iteration, the variable i is 
}

现在执行第一个异步函数:

db.returnTotalInvestingfromValidatedInvests(List[i],function(err,rst){
     /*this is an async callback which will be executed in a 
     different context in a later time, when the response is received*/
}

所发生的是执行for循环的主要执行不等待来自上述函数的响应(因为异步),并向前递增递增执行下一次迭代的变量i使用您的函数db.returnTotalInvestingfromValidatedInvests并继续它。 无论你的所有或任何回复是否已经到来,很快整个for循环就会结束。

您获得undefined的原因是因为在循环结束时变量i的值为List.length,这意味着它正在访问List[list.length] 。由于最大索引始终为length-1,因此始终未定义。

摘要:您必须以List[i]某种方式跟踪元素,以便在触发最终(嵌套)函数的异步回调时,您可以更新正确的元素。有些人通过创建哈希来做到这一点,有些人通过将其逻辑转换为循环方式来实现同步。

<强>建议:

尝试在每个函数回调中注销i,以查看快速更改的变量。

希望解释有所帮助:)

根据要求,这是一种方法:

  function onInvestsDone(err, obj){
    if(err!=null){
      // something went wrong
    }
    else{
      // do anything here with your final response
    }
  }

  for(var i=0;i<List.length;i++){
    returnInvests(List, i, onInvestsDone);    
  }



  function returnInvests(listArray, index, cb){
    db.returnTotalInvestingfromValidatedInvests(listArray[index],function(err,rst){
      if(err){
        console.log(err);
        cb(err);  // call callback with error
      }
      console.log(rst);
      var dailySaving = ((rst*multiplier)/100);
      console.log('Daily Savings which is going to be added is that  :  ' +dailySaving);
      console.log(listArray[index]);
      db.multiplyInvestAndAddSavings(listArray[index],dailySaving,function(err,rest){
        if(err){
          console.log(err);
          cb(err);  // call callback with error
        }
        console.log(rest);
        // successfully done everything
        cb(null, rest);
      });

    });
  }