这里似乎有很多关于这个问题的问题,但没有一个与我的问题AFAICT直接相关。这是问题陈述:
此问题与上一个问题(HTTP COLLECT)相同,因为您需要使用http.get()。但是,这次您将获得三个URL作为前三个命令行参数。
您必须收集每个网址提供给您的完整内容,然后将其打印到控制台(标准输出)。您不需要打印长度,只需将数据打印为String;每个网址一行。问题在于您必须按照与作为命令行参数提供的URL相同的顺序打印它们。
这是我失败的原始解决方案:
var http = require('http')
var concat = require('concat-stream')
var args = process.argv.slice(2, 5)
var args_len = args.length
var results = []
args.forEach(function(arg, i) {
http.get(arg, function(res) {
res.setEncoding('utf8')
res.pipe(concat(function(str) {
results[i] = str
if (results.length === args_len)
results.forEach(function(val) {
console.log(val)
})
}))
}).on('error', console.error)
})
这是他们推荐的解决方案:
var http = require('http')
var bl = require('bl')
var results = []
var count = 0
function printResults () {
for (var i = 0; i < 3; i++)
console.log(results[i])
}
function httpGet (index) {
http.get(process.argv[2 + index], function (response) {
response.pipe(bl(function (err, data) {
if (err)
return console.error(err)
results[index] = data.toString()
count++
if (count == 3)
printResults()
}))
})
}
for (var i = 0; i < 3; i++)
httpGet(i)
我未能理解的是我的代码与官方解决方案之间的根本区别。在将回复填充到数组中以便稍后引用时,我的解决方案与其解决方案相同。当我比较两个数组的长度(一个长度增加每个回调的数组)时,它们使用计数器来计算回调的数量;那有关系吗?当我在learnyounode
程序的范围之外尝试我的解决方案时,似乎工作正常。但我知道这可能意味着很少......所以有人比我更了解节点......关心解释我哪里出错了? TIA。
答案 0 :(得分:0)
当我比较两个数组的长度(一个长度增加每个回调的数组)时,他们使用计数器来计算回调的数量;这有关系吗?
是的,这很重要。 .length
of an array取决于数组中的最高索引,而不是实际分配的元素数。
仅当异步请求的结果返回乱序时才会出现差异。如果您首先分配索引0
,然后分配1
,然后分配2
等等,则.length
会匹配已分配元素的数量,并且与{{1}相同}}呃。但现在试试这个:
count
如果您在每次分配后测试长度并在获得var results = []
console.log(results.length) // 0 - as expected
results[1] = "lo ";
console.log(results.length) // 2 - sic!
results[0] = "Hel";
console.log(results.length) // 2 - didn't change!
results[3] = "ld!";
console.log(results.length) // 4
results[2] = "Wor";
console.log(results.length) // 4
时输出数组,则会打印
4
答案 1 :(得分:0)
所以事实证明这里有两个不同的问题,其中一个是由@Bergi在上面指出的。这两个问题如下:
.length
方法实际上并不返回数组中的元素数。而是返回可用的最高索引。这看起来很傻。感谢@Bergi指出这一点。i
变量的范围不合适,因此i
的值可能会发生变化。当结果回来时,这会导致竞争状态。我的最终解决方案最终如下:
var http = require('http')
var concat = require('concat-stream')
var args = process.argv.slice(2, 5)
var args_len = args.length
var results = []
var count = 0
function get_url_save(url, idx) {
http.get(url, function(res) {
res.setEncoding('utf8')
res.pipe(concat(function(str) {
results[idx] = str
if (++count === args_len)
results.forEach(function(val) {
console.log(val)
})
}))
}).on('error', console.error)
}
args.forEach(function(arg, i) {
get_url_save(arg, i)
})
将outtermost forEach
分解为方法调用可以解决更改i
问题,因为i
作为参数逐个传入,因此永远不会更改。计数器的添加解决了@Bergi描述的问题,因为.length
方法并不像人们想象的那样直观。