我遇到与this question相同的问题,但无法解决问题。我正在尝试编写一个nodejs脚本,它将首先检查mongo中的缓存值,但如果它不存在则继续计算它。问题是findOne()回调不会获得循环变量的原始值,因此回调无法正确计算和存储该值。 (我省略了实际的提取,存储和返回以关注我所拥有的实际问题)。无论我做什么,我都无法获得原始值以反馈回调。
for (var d=start_date; d<now; d.setHours(d.getHours()+1)) {
(function(key) {
console.log('caller='+key)
db.collection('avgs').findOne( { date: key.toISOString() },function (err,data) {
console.log('callback='+key);
if (data) { //return data }
else { // compute average for given date , insert into database and return value }
});
})(d);
};
控制台日志显示此
caller=Tue Mar 25 2014 00:00:00 GMT+1030 (CST)
caller=Tue Mar 25 2014 01:00:00 GMT+1030 (CST)
caller=Tue Mar 25 2014 02:00:00 GMT+1030 (CST)
caller=Tue Mar 25 2014 03:00:00 GMT+1030 (CST)
callback=Wed Mar 26 2014 14:00:00 GMT+1030 (CST)
callback=Wed Mar 26 2014 14:00:00 GMT+1030 (CST)
callback=Wed Mar 26 2014 14:00:00 GMT+1030 (CST)
callback=Wed Mar 26 2014 14:00:00 GMT+1030 (CST)
答案 0 :(得分:3)
我猜你的问题是你将值d
发送到包装函数,并在该函数内以某种方式修改该值。由于d
是对循环迭代器的引用,因此修改它会修改循环。解决方案是在函数内创建对象的副本:
for (var d=start_date; d<now; d.setHours(d.getHours()+1)) {
(function(_key) {
// Make a copy of the object you passed in, so that modifying it
// won't screw up your loop
var key = new Date(_key);
console.log('caller='+key)
db.collection('avgs').findOne( { date: key.toISOString() },function (err,data) {
console.log('callback='+key);
if (data) { //return data }
else { // compute average for given date , insert into database and return value }
});
})(d);
};
答案 1 :(得分:0)
使用创建循环变量副本的技术,我发现我也能够使用bind()来获得相同的结果。相同的结果,但代码读起来更好。
db.collection('avgs').findOne( { date: key.toISOString() },found.bind(this,new Date(d));
function found(key,err,data) {
console.log('callback='+key);
if (data) { //return data }
else { // compute average for given date , insert into database and return
};
看来javascript通常会传递引用而不是值not always