Learnyounode - Jugglling Async (#9) - I Must Be Missing Something
Solution 1:
They use a counter to count the number of callbacks while I am comparing the length of two arrays (one whose length increases every callback); does that matter?
Yes, it does matter. The .length
of an array depends on the highest index in the array, not the actual number of assigned elements.
The difference surfaces only when the results from the asynchronous requests come back out of order. If you first assign index 0
, then 1
, then 2
and so on, the .length
matches the number of assigned elements and would be the same as their count
er. But now try out this:
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
If you would test the length after each assignment and output the array whenever you get 4
, it would print
"Hello ld!""Hello World!"
Solution 2:
So it turns out there were two different issues here, one of which was pointed out by @Bergi above. The two issues are as follows:
- The
.length
method does not actually return the number of elements in the array. Rather it returns the highest index that is available. This seems quite silly. Thanks to @Bergi for pointing this out. - The scoping of the
i
variable is improper, and as such the value ofi
can change. This causes a race condition when results come back.
My final solution ended up being as follows:
var http = require('http')
var concat = require('concat-stream')
var args = process.argv.slice(2, 5)
var args_len = args.lengthvar results = []
var count = 0functionget_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)
})
Breaking the outtermost forEach
into a method call solves the changing i
issue since i
gets passed in as parameter by value, thus never changing. The addition of the counter solves the issue described by @Bergi since the .length
method isn't as intuitive as one would imagine.
Post a Comment for "Learnyounode - Jugglling Async (#9) - I Must Be Missing Something"