我正在通过learnyounode exercises from nodeschool学习节点。 在第8次练习中,他们要求编写一个执行以下操作的程序:
他们简要提到了异步库的存在,它们有助于计算回调,但他们也邀请完成没有它们的练习。我的初步解决方案如下:
var http = require('http');
var bl = require('bl');
var results = Array();
var count = 0;
function printResults() {
for (var i = 0; i < 3; i++) {
console.log(results[i]);
}
}
for (var index = 0; index < 3; index++)
http.get(process.argv[2+index], function(response) {
response.pipe(bl(function(err,data){
if(err) console.error(err)
results[index] = data.toString();
count++;
if(count==3) printResults(results);
}));
});
}
然而,由于某种原因,这会打印三次“未定义”。我碰巧通过简单地用函数替换for循环并将该函数的调用封闭在另一个for循环中来找到正确的解决方案。
(...)
function httpGet (index) {
http.get(process.argv[2+index], function(response) {
response.pipe(bl(function(err,data){
if(err) console.error(err)
results[index] = data.toString();
count++;
if(count==3) printResults(results);
}));
});
}
for (var i = 0; i < 3; i++)
httpGet(i)
但是,我不明白 这种差异究竟是什么让解决方案有效。有人可以赐教我吗?
答案 0 :(得分:4)
在您的代码中,您传递对迭代变量的引用,因此在调用回调时它等于3.参见此示例:
编辑:我忘了总结一下,你的代码将无法正常工作,因为回调将所有结果设置为结果数组的索引3并且你打印出从0到2的索引
for(var index = 0; index < 3; index++){
setTimeout(function(){
console.log(index);
}, 500);
}
通过创建功能,您可以添加更多范围:
function fun(index){
setTimeout(function(){
console.log(index);
}, 500);
}
for(var index = 0; index < 3; index++){
fun(index);
}
你仍然可以使用匿名功能,但你需要用这样的范围包围它:
for(var index = 0; index < 3; index++){
setTimeout((function(index){
return function(){
console.log(index);
}
})(index), 500);
}
为了使它更清楚一点,我将使变量名在范围和范围之间不同:
for(var outerIndexVariable = 0; outerIndexVariable < 3; outerIndexVariable++){
setTimeout((function(innerIndexVariable){
return function(){
console.log(innerIndexVariable);
}
})(outerIndexVariable), 500);
}