附件是有问题的代码。
var http = require("http");
var i = 0;
var hostNames = ['www.1800autoland.com','www.youtube.com','www.1800contacts.com'];
for(i;i<hostNames.length;i++){
var options = {
host: hostNames[i],
path: '/'
};
http.get(options, function(res){
console.log("url: " + hostNames[i]);
console.log("status: " + res.statusCode);
for(var item in res.headers){
if(item == "server"){
console.log(item + ": " + res.headers[item]);
}
if(item == "x-powered-by"){
console.log(item + ": " + res.headers[item]);
}
if(item == "x-aspnet-version"){
console.log(item + ": " + res.headers[item]);
}
}
console.log("\n");
})
};
我有一系列的URL,我来咨询该网站的问题是,在我的代码中,hostNames [i]不会将第n个(或本例中的“i”)索引显示为字符串。控制台中的输出始终是“未定义的”。我已经尝试过String(),toString()和许多不同的方法无济于事。有人能指出我正确的方向吗?我需要做什么转换?
答案 0 :(得分:3)
这是因异步而发生的典型闭包问题。当您的回调触发时,i
的值始终为hostNames.length
。
要围绕i
:
http.get(options, (function(res) { // '(' before function is optional, I use it to indicate immediate invocation
return function (i) { // this is the closed value for i
console.log("url: " + hostNames[i]);
console.log("status: " + res.statusCode);
// .. etc
};
}(i))); // immediate invocation with i
使用这样的闭包实现的重要之处在于,您正在创建一些匿名函数,而不仅仅是一个函数。每个函数都绑定到自己的值i
。
避免编写这些奇怪代码的最简单方法是不直接使用for
循环,而是使用map
函数。像:
function array_map(array, callback) {
var i, len = array.length;
for (i = 0; i < len; i += 1) {
callback(i, array[i]);
}
}
这样可以自动关闭i
的值。你的循环看起来像:
array_map(hostNames, function(i, hostname) { // i and hostname have the closed value
// .. etc
});
答案 1 :(得分:1)
这是closure问题,试试这个:
(function (i) {
http.get(options, function(res){
console.log("url: " + hostNames[i]);
console.log("status: " + res.statusCode);
for(var item in res.headers){
if(item == "server"){
console.log(item + ": " + res.headers[item]);
}
if(item == "x-powered-by"){
console.log(item + ": " + res.headers[item]);
}
if(item == "x-aspnet-version"){
console.log(item + ": " + res.headers[item]);
}
}
console.log("\n");
})
})(i);
答案 2 :(得分:0)
您应该使用.get(i)方法来检索项目。您不需要像其他人所说的那样初始化阵列中的计数器。