为什么这个while循环调用它的内部函数?

时间:2017-07-25 08:56:28

标签: javascript node.js http get

我正在尝试编写一个函数,它将3个url作为命令行参数,并以正确的顺序记录它们的内容。

我使用while循环,所以我可以阻止http.get的执行,直到它的内容被记录在END上,即使是响应。

var http = require('http')

var url1 = process.argv[2]
var url2 = process.argv[3]
var url3 = process.argv[4]

var urls = [url1, url2, url3]


while (urls.length>0){
    var url = urls[0]
    http.get(url, function callback(response){
    var chars = ""
    response.on('data', function(data){
        chars+=data.toString()
    })
    response.on('end', function(err){
        console.log(chars)
        urls.shift()
    })
    })
}

我必须做一些非常错误的事情,因为代码会导致无限循环(显然不会调用urls.shift())。任何人都可以解释错误吗?

2 个答案:

答案 0 :(得分:1)

如果回复完成,你只是转移。因此,如果while循环运行,它永远不会移动,你有无限。可以简单地在循环中移位,例如:

while(urls.length){
  var url=urls.shift();
   ...
}

答案 1 :(得分:1)

这里的问题是while循环是非阻塞的,因为http.get是非阻塞的。因此,您必须找到一种使用回调按顺序请求这些URL的方法。如果您愿意使用async模块,可以按如下方式实现它......

var http = require('http');
var async = require('async');

var url1 = process.argv[2]
var url2 = process.argv[3]
var url3 = process.argv[4]

var urls = [url1, url2, url3]

var results = [];

async.eachOf(urls, function(url, index, callback) {
    http.get(url, function (res) {
        var chars = "";
        res.on('data', function(data){
            chars += data.toString();
        })
        res.on('end', function(err){
            results[index] = (chars);
            callback(null, chars);
        })
    })
}, function (err) {
    console.log(results);
});

如果您不想使用async模块,那么您必须在while循环中手动跟踪待处理的网址请求,如下所示。

请注意使用立即调用的函数表达式(IIFE)来跟踪执行上下文中的当前URL。这需要完成,因为您需要与提供的URL顺序相同的结果排序...

var http = require('http');
var url1 = process.argv[2]
var url2 = process.argv[3]
var url3 = process.argv[4]

var urls = [url1, url2, url3]

var total = urls.length;
var results = [];
var processed = 0;

while (urls.length>0){
    (function(url, index) {
        http.get(url, function callback(response){
            var chars = ""
            response.on('data', function(data){
                chars+=data.toString()
            })
            response.on('end', function(err){
                results[index] = chars;
                processed++;

                if(processed === total) {
                    // do something with the result
                    console.log(results);
                }
            })
        })
    })(urls.shift(), total - urls.length - 1);
}