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);
如果bills
是Array
或者如果您使用像Lo-Dash 这样的实用程序库,您可以使用像Array.prototype.map
或lodash.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() 回调问题的主要内容,如果未能解决你的问题,请参考以下文章