我正在使用learnyounode
学习node.js。
我遇到了JUGGLING ASYNC
的问题。
问题描述如下:
您将获得三个URL作为命令行参数。您应该进行http.get()
调用以从这些URL中获取数据,然后按照与参数列表中的顺序相同的顺序打印它们。
这是我的代码:
var http = require('http')
var truecount = 0;
var printlist = []
for(var i = 2; i < process.argv.length; i++) {
http.get(process.argv[i], function(response) {
var printdata = "";
response.setEncoding('utf8');
response.on('data', function(data) {
printdata += data;
})
response.on('end', function() {
truecount += 1
printlist.push(printdata)
if(truecount == 3) {
printlist.forEach(function(item) {
console.log(item)
})
}
})
})
}
以下是我不明白的问题:
我正在尝试使用字典将完成的数据存储在每个URL的response.on('end', function(){})
中。但是,我不知道如何获取http.get()
的网址。如果我可以在http.get()
中做一个局部变量,那就太棒了但我想每当我将变量声明为var url
时,它总是指向最后一个url。因为它是全局的并且它通过循环不断更新。我将这些已完成数据存储为密钥等于url的值的最佳方法是什么?
答案 0 :(得分:12)
这就是解决问题的方法。
#!/usr/bin/env node
var http = require('http');
var argv = process.argv.splice(2),
truecount = argv.length,
pages = [];
function printUrls() {
if (--truecount > 0)
return;
for (i = 0; i < pages.length; i++) {
console.log(pages[i].data + '\n\n');
}
}
function HTMLPage(url) {
var _page = this;
_page.data = '### [URL](' + url + ')\n';
http.get(url, function(res) {
res.setEncoding('utf8');
res.on('data', function(data) {
_page.data += data;
});
res.on('end', printUrls);
});
}
for (var i = 0; i < argv.length; i++)
pages.push(new HTMLPage(argv[i]));
它在每个请求开始时将请求添加到数组中,这样一旦完成,我可以很好地遍历响应,知道它们的顺序正确。
在处理异步处理时,我发现将每个进程视为具体的开始和结束更容易。如果您需要保留请求的顺序,则必须在创建每个进程时进行输入,然后在完成时返回该记录。只有这样才能保证你的东西顺序正确。
如果你急于使用上面的方法,那么你可以在你的get回调闭包中定义一个变量并使用它来存储url,这样你就不会最后一个url覆盖你的变量了。但是,如果你这样做,当你必须使用process.argv中的url来按顺序访问每个响应时,你将大大增加你的开销。我不建议。
答案 1 :(得分:0)
我对这一挑战的看法略有不同。我正在创建一个调用http.get的函数数组,并立即使用它们的特定上下文调用它们。流写入对象,其中密钥是与该流相关的服务器的端口。当触发结束事件时,它会将该服务器添加到已完成的数组中 - 当该数组已满时,它会按服务器的原始顺序进行迭代并回显。
没有正确的方法,但可能有十几种方式。想和我分享。
var http = require('http'),
request = [],
dataStrings = {},
orderOfServerInputs = [];
var completeResponses = [];
for(server in process.argv){
if(server >= 2){
orderOfServerInputs[orderOfServerInputs.length] = process.argv[server].substr(-4);
request[request.length] = function(thisServer){
http.get(process.argv[server], function(response){
response.on("data", function(data){
dataStrings[thisServer.substr(-4)] = dataStrings[thisServer.substr(-4)] ? dataStrings[thisServer.substr(-4)] : ''; //if not set set to ''
dataStrings[thisServer.substr(-4)] += data.toString();
});
response.on("end", function(data){
completeResponses[completeResponses.length] = true;
if(completeResponses.length > 2){
for(item in orderOfServerInputs){
serverNo = orderOfServerInputs[item].substr(-4)
console.log(dataStrings[serverNo]);
}
}
});
});
}(process.argv[server]);
}
}
答案 2 :(得分:0)
立即调用函数表达式(IIFE)可以解决您的问题。它允许我们绑定函数一个特定的值,在你的情况下,获取响应的url。在下面的代码中,我将变量i
绑定到index
,因此,无论哪个url获得响应,都将更新打印列表的索引。有关更多信息,请参阅this website
var http = require('http')
var truecount = 0;
var printlist = [];
for(var i = 2; i < process.argv.length; i++) {
(function(index){
http.get(process.argv[index], function(response) {
response.setEncoding('utf8');
response.on('data', function(data) {
if (printlist[index] == undefined)
printlist[index] = data;
else
printlist[index]+= data;
})
response.on('end', function() {
truecount += 1
if(truecount == 3) {
printlist.forEach(function(item) {
console.log(item)
})
}
})
})
})(i)
}