Mongoose find() 回调问题

Posted

技术标签:

【中文标题】Mongoose find() 回调问题【英文标题】:Mongoose find() issues with callbacks 【发布时间】: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。此外,您的建议将不起作用,因为该项目代表我数组中的键。 【参考方案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);  
);

【讨论】:

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

以上是关于Mongoose find() 回调问题的主要内容,如果未能解决你的问题,请参考以下文章

mongo+mongoose+express

Mongoose 中的 Mongo BSON 类型

Mongoose 中的 Mongo BSON 类型

Mongo (+Mongoose) 错误:无法找到 $geoNear 查询的索引

在使用 mongoose 完成两个异步查询后进行回调

查看单个文档的数组时,mongoose .find() 没有结果