0

I am trying to solve the Juggling Async problem of learnyounode.

The following is what I have tried. But I am not getting desired output. I can find the solution by searching in google. But what I want is to learn node fundamentals. Can somebody direct me where I am going wrong?

var http = require('http');
var bl = require('bl');
var output = [];
var cnt = 0;

for (var i in process.argv) {
  if (i > 1 ) {
    http.get(process.argv[i],function(response){
      response.pipe(bl(function(err,data){
        output[cnt] = data.toString();
        cnt++;
        if (output.length === (process.argv.length - 2)) {
          printResult(output);
        }
      }));
    });
  }
}

function printResult(output){
  for (var i = 0; i < output.length; i++) {
    console.log(output[i]);
  }
}

The output I am getting:

  1. ACTUAL: "Gutful of brickie where shazza got us some ripper. Come a bunyip with watch out for the dinky-di. You little ripper rotten mate lets get some larrikin. "
  2. EXPECTED: "Gutful of brickie where shazza got us some ripper. Come a bunyip with watch out for the dinky-di. You little ripper rotten mate lets get some larrikin. "

  3. ACTUAL: "Watch out for the aerial pingpong when she'll be right aussie rules footy. He hasn't got a battler mate lets throw a battler. "

  4. EXPECTED: "Built like a feral no worries stands out like a bonzer. Come a grundies my flat out like a boardies. As dry as a mokkies no worries shazza got us some rock up. "

  5. ACTUAL: "Built like a feral no worries stands out like a bonzer. Come a grundies my flat out like a boardies. As dry as a mokkies no worries shazza got us some rock up. "

  6. EXPECTED: "Watch out for the aerial pingpong when she'll be right aussie rules footy. He hasn't got a battler mate lets throw a battler. "

  7. ACTUAL: ""

  8. EXPECTED: ""
Dushyant Joshi
  • 3,672
  • 3
  • 28
  • 52

1 Answers1

2

If I remember the problem correctly you have to print the responses in the same order as the URLs are provided in the command line argument.

The issue with your solution is that you are not actually storing your responses in correct order.
This part of your code:

// ...
output[cnt] = data.toString();
cnt++;
// ....

You fired three http request asynchronously and you are saving the response in output array using the counter cnt. Since response can arrive in any order there is no guarantee that the responses will be saved in the same order as the request were fired. For example if response for the Request 3rd came first it will be stored at index 0 in output array which is not what you want.

To fix this problem instead of using independent counter. Use the existing variable i which was used to fire the http requests. So for request 1 response will be saved at index 0, for request 2 response will be saved at index 1 and so on.

Write you http get request in separate function and pass the index i and use this index i to save your responses.

//....
for (var i in process.argv) {
    if (i > 1) {
        httpGet(i);
    }
}


function httpGet(index) {
    http.get(process.argv[index], function(response) {
        response.pipe(bl(function(err, data) {
            output[index - 2] = data.toString();
            cnt++;
            // Use cnt to decide if all the responses have arrived and then print
            if (cnt === (process.argv.length - 2)) {
                printResult(output);
            }
        }));
    });
}
// .....

http get request needs to wrapped in a separate function otherwise, the value of variable i inside the anonymous function of response block will be same for each functions (which will be 4 in this case). This is classic closure problem. I suggest you to read these to get the detailed explanation:

JavaScript closure inside loops – simple practical example

Creating closures in loops: A common mistake

Let me know if this worked for you.

abhishekkannojia
  • 2,796
  • 23
  • 32