我的for循环只有一个问题,如果阻塞有效。 我必须从API是否获得温度并使用我的put方法将其放回到我的桌子中。 问题是我无法填补所有城市。 如何使用ASYNC(https://caolan.github.io/async)模块进行循环工作? 这是我的代码:
for (i in guests) {
ville = i[ville_id];
guest_id = i._id;
if (ville) {
results.push(req2 = http.get('http://api.openweathermap.org/data/2.5/weather?q=' + ville + ',france&APPID=xxx', function(res) {
return res.on('data', function(chunk) {
var options, test, url;
test = chunk.toString();
obj = JSON.parse(test);
res = obj.main.temp;
i[temp_id] = res;
url = update_guest + guest_id.toString();
options = {
method: 'PUT',
url: update_guest + guest_id,
qs: {
api_key: 'xxx'
},
headers: {
'Cache-Control': 'no-cache',
'Content-Type': 'application/json'
},
body: {
'595f9b2a5ea9cb0004c21290': res
},
json: true
};
return request(options, function(error, response, body) {
if (error) {
throw new Error(error);
}
return console.log(body);
});
});
}));
}
}

答案 0 :(得分:0)
由于closures的工作方式,这是JavaScript中非常常见的问题。发生了什么事情是你的循环for (i in guests)
在你的任何回调(function(res){...}
)有机会运行之前完成。您的回调引用变量i
,但它们不会“记住”您发出HTTP请求时i
的值。相反,当你的回调执行时,i
将是guests
中的最后一个值,因为你的for...in
循环在你的回调执行时已经完成了。
例如,假设guests
中有两个键,guest1
和guest2
。这是将要发生的事情:
i
现在是guest1
。第一个HTTP请求被触发。i
现在是guest2
。第二个HTTP请求被触发。i
设置为guest2
。因此,对i
的回调引用都是guest2
。您需要做的是找到一种方法,让您的回调在您的请求被解雇时访问i
的值。您可以通过使用i
作为参数的函数创建回调来实现此目的:
for (i in guests) {
ville = i[ville_id];
guest_id = i._id;
if (ville) {
results.push(req2 = http.get('http://api.openweathermap.org/data/2.5/weather?q=' + ville + ',france&APPID=xxx', (function (localI) { return function(res) {
return res.on('data', function(chunk) {
// removing code for clarity
localI[temp_id] = res;
// removing code for clarity
return request(options, function(error, response, body) {
// removing code for clarity
});
});
})(i)));
}
}
您可以详细了解此方法here。
我所做的是创建了一个函数,它返回你的回调并获取参数localI
。然后我立即将i
作为该参数传递,并将localI
设置为当前值i
的回调返回。然后我将回调中的i
引用更改为localI
。 请注意,您在回调中对ville
和guest_id
的引用也会遇到与i
相同的问题。您需要将这些引用作为参数传递给好吧或在你的回调中声明它们。