【问题标题】:NodeJs - Nested Functions with a for loop which does not work properly insideNodeJs - 带有 for 循环的嵌套函数在内部无法正常工作
【发布时间】:2017-03-19 09:05:38
【问题描述】:

今天我的问题实际上是关于由于循环无法正常工作而发生的问题,但无论如何,如果我在设计方面遇到问题,我对想法持开放态度。

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

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

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

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();
});
}

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();
});
}

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();
});
}

输出是:

在列表范围内> 让我们说 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

【问题讨论】:

  • 循环“无法正常工作”:尽管有代码,请更准确:它的行为如何/应该如何工作?
  • 请提供minimal reproducible example,而不是代码转储和模糊描述。
  • 好的,请稍等,我将添加预期和正常输出

标签: node.js mongodb loops callback nested


【解决方案1】:

问题在于您使用的是内部带有异步功能的 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 使用您的函数执行下一次迭代 @ 987654324@ 及以后。 很快整个 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);
      });

    });
  }

【讨论】:

  • 我理解你的意思,它不会等待响应并不断增加 "i" 。非常感谢您澄清其背后的原因,我仍然对如何提供一个等待响应并以精确数据前进的解决方案感到困惑。你能帮我吗?我的意思是你能给我一个你建议的例子吗?
  • 是的,我会添加到答案中
  • 用 sn-p 更新了答案。不要忘记投票;)
猜你喜欢
  • 1970-01-01
  • 2022-01-18
  • 1970-01-01
  • 2016-04-01
  • 2013-10-09
  • 1970-01-01
  • 2019-04-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多