【问题标题】:Mongoose find() issues with callbacksMongoose find() 回调问题
【发布时间】:2015-03-01 12:35:12
【问题描述】:

我找不到让我的查找功能正常工作的方法。 我想从 bills 集合中找到所有 billId,然后检查事务数据库中的每个 billId。

问题是,由于 aSynch - 我认为,id 不会在我的循环中更新。 代码如下:

Bills.find({type: bill_type, endDate: {"$gte" : new Date(year + "-" + month + "-1")}}).find(function(err, bills){
        if(err)
            res.send(err);

        details.bills = bills;

        for(key in bills){
            var billId = bills[key]._id;
            console.log("BillId: " + billId); // Here the ids are unique (which is what I want)

             Transactions.find({billId : billId}, function(err, transactions){
                if (err) {
                    console.log('error: '+ err)
                } else {
                    console.log("Transaction BillId: " + billId); // Here I get always the same ID - which is not quiet what I need.
                }
            });


            //console.log(transactions);
        }

       res.send(details);  
    });

控制台的结果是:

BillId: 549bf0597886c3763e000001
BillId: 54a014bfac01ca3526000001
BillId: 54a015753547a6c026000001

^ 好结果 - 来自 for() 中的第一个 console.log。

然后:

Transaction BillId: 54a015753547a6c026000001
Transaction BillId: 54a015753547a6c026000001
Transaction BillId: 54a015753547a6c026000001

^ 错误的结果 - 它重复了 for() 的最后一个结果,我需要所有结果。

在第一个 console.log() 中,当我从第一个 find() (Bills.find()) 获得结果时,我可以看到日志上的所有 id,但是当我尝试将它们放入第二个 Find ( Transactions.find()),他们重复最后一个 id。 因此,在当前状态下,我无法为每个 id 查询数据库。对此的任何帮助表示赞赏。

如果您需要任何说明,请告诉我。

提前致谢!

【问题讨论】:

  • var billId = bills[item]._id; 应该是 var billId = item._id
  • 这不是重点。我在那里得到了 billId,问题是当我尝试对每个 billId 执行 Transactions.Find() 时,billId 始终是来自 Bills.find() 的最后一个 billId。此外,您的建议将不起作用,因为该项目代表我数组中的键。

标签: javascript node.js callback mongoose


【解决方案1】:

循环内闭包函数的经典错误。

您的变量值会在每个循环步骤中发生变化。另一方面,当变量已经多次更改时,您的函数将在稍后(一段时间后)执行。

查看链接以进行澄清:

Creating closures in loops: A common mistake

JavaScript closure inside loops – simple practical example

Javascript infamous Loop issue?

【讨论】:

    【解决方案2】:

    如果你的Transactions.find 函数是异步的,它的回调会在稍后的时间点运行,在for ... in 循环结束很久之后。那时,billId 具有在最后一次运行 for ... in 循环时分配的值。因此,回调的所有运行都会打印出该值。

    如果您想保留该值,则必须在某处创建closure,如下所示:

    (function (id) {
        Transactions.find(..., function (...) {
            // ... use `id` here
        });
    })(billId);
    

    如果billsArray 或者如果您使用像Lo-Dash 这样的实用程序库,您可以使用像Array.prototype.maplodash.each 这样使用闭包的迭代函数,这样您就不会必须单独创建一个。

    【讨论】:

      【解决方案3】:

      完美!

      感谢您的提示。我使用Underscore each function 解决了它。

      方法如下: 我没有使用for 循环,而是简单地将for 替换为_.each,如下例所示:

      Bills.find({type: bill_type, endDate: {"$gte" : new Date(year + "-" + month + "-1")}}).find(function(err, bills){
          if(err)
              res.send(err);
      
          details.bills = bills;
      
          _.each(bills, function(item){        
              var billId = item._id; 
              console.log("BillId: " + billId); 
      
               Transactions.find({billId : billId}, function(err, transactions){
                  if (err) {
                      console.log('error: '+ err)
                  } else {
                      console.log("Transaction BillId: " + billId);
                  }
              });
      
      
              //console.log(transactions);
          });
      
         res.send(details);  
      });
      

      【讨论】:

      • 如果某个答案解决了您的问题,最好将其标记为已接受,而不是在单独的答案中稍作改动而重新发布整个代码。
      • 谢谢!但我实际上喜欢发布解决问题的确切方法,因为我相信这里的每个人都不是像你们这样的专家,而且建议并不总是能说明你需要做什么才能解决问题。因此,发布正确的解决方案将帮助像我这样的其他业余爱好者。
      猜你喜欢
      • 1970-01-01
      • 2016-01-08
      • 1970-01-01
      • 1970-01-01
      • 2018-10-13
      • 2019-06-04
      • 1970-01-01
      • 2011-11-17
      • 1970-01-01
      相关资源
      最近更新 更多