1

I'm new to javascript and node.js, so this might be basic javascript problem..

I'm solving this Juggling Async problem in LearnYouNode, but I don't know why my code isn't working.

my code:

const http = require('http');

var URLs = [process.argv[2], process.argv[3], process.argv[4]];
var strs = ["", "", ""];
var ctr = 0;

for(var i = 0; i < 3; i++){
    http.get(URLs[i], (response) => {
        response.setEncoding('utf8');
        response.on('data', (data) => {
            strs[i] += data;
        });
        response.on('end', () => {
            ctr++;
            if(ctr == 3){
                console.log(strs[0]);
                console.log(strs[1]);
                console.log(strs[2]);
            }
        });
    });
}

My code doesn't work, but this code does:

const http = require('http');

var URLs = [process.argv[2], process.argv[3], process.argv[4]];
var strs = ["", "", ""];
var ctr = 0;

function httpGet(i){
    http.get(URLs[i], (response) => {
        response.setEncoding('utf8');
        response.on('data', (data) => {
            strs[i] += data;
        });
        response.on('end', () => {
            ctr++;
            if(ctr == 3){
                console.log(strs[0]);
                console.log(strs[1]);
                console.log(strs[2]);
            }
        });
    });
}

for(var i = 0; i < 3; i++){
    httpGet(i);
}

The code works only by making it as a function. Why is this?

EDIT: the problem is that the "strs[i] += data" part doesn't work!

  1. ACTUAL: ""
  2. EXPECTED: "As cross as a turps how gutful of freckle. You little ripper gone walkabout mate you little ripper khe sanh. "

  3. ACTUAL: ""

  4. EXPECTED: "As dry as a milk bar when mad as a ambo. Stands out like a stickybeak my lets get some larrikin. He hasn't got a budgie smugglers and stands out like a show pony. "

  5. ACTUAL: ""

  6. EXPECTED: "You little ripper cockie where we're going digger. Grab us a bush oyster heaps you little ripper dero. Lets get some apples mate gutful of compo. "

  7. ACTUAL: ""

  8. EXPECTED: ""
Ho.L
  • 13
  • 3
  • What part doesn't work? What errors do you get? – MarthyM Jul 30 '17 at 16:02
  • Possible duplicate of [JavaScript closure inside loops – simple practical example](https://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) – Jonas Wilms Jul 30 '17 at 16:15

2 Answers2

0

When the http.get run the value of ' i ' is 2 in the loop ' for ' because it is the last value that ' i' has in loop. Instead in function the value is correct ' 0 ' ' 1' and '2' because passing the ' i ' in function you have a local variable in function.

It is related to the closure: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures

asv
  • 3,332
  • 7
  • 24
  • 47
0

The reason why wrapping the async method in a function works better is because the passed on index i is the same as the expected index.

for (var i = 0; i < 3; i++) {
    setTimeout(function() {
        console.log(i)
    }, 1000);
}

The output is always 3, because the for loop finishes before the async method is done with the call.

You can however use the let keyword in es6 to keep blocked scope variables.

for (let i = 0; i < 3; i++) {
    setTimeout(function() {
        console.log(i)
    }, 1000);
}
Shane
  • 3,049
  • 1
  • 17
  • 18