Node.js中的异步http.get调用(Learyounode练习)

时间:2017-04-24 00:02:47

标签: javascript node.js asynchronous

我正在通过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)

但是,我不明白 这种差异究竟是什么让解决方案有效。有人可以赐教我吗?

1 个答案:

答案 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);
}