Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

learnyounode #9 juggling async

I am trying to go through nodeschool's learnyounode.

This problem is the same as the previous problem (HTTP COLLECT) in that you need to use http.get(). However, this time you will be provided with three URLs as the first three command-line arguments.

You must collect the complete content provided to you by each of the URLs and print it to the console (stdout). You don't need to print out the length, just the data as a String; one line per URL. The catch is that you must print them out in the same order as the URLs are provided to you as command-line arguments.

I'm confused as to why my solution doesn't work exactly since it looks the same to me but more functional and am unsure of their inner test workings:

1.  ACTUAL:    ""
1.  EXPECTED:  "As busy as a dead horse also lets get some dero. Built like a sleepout no dramas lets get some chook. She'll be right thingo my she'll be right ute. "

2.  ACTUAL:    "She'll be right bizzo no worries she'll be right fair dinkum. We're going aerial pingpong no worries as busy as a gyno. "
2.  EXPECTED:  "She'll be right bizzo no worries she'll be right fair dinkum. We're going aerial pingpong no worries as busy as a gyno. "

3.  ACTUAL:    "He's got a massive pretty spiffy heaps she'll be right brizzie. He hasn't got a fly wire where shazza got us some strewth. She'll be right spit the dummy with it'll be fair go. We're going gobsmacked with as stands out like arvo. He's got a massive bush bash mate she'll be right slacker. "
3.  EXPECTED:  "He's got a massive pretty spiffy heaps she'll be right brizzie. He hasn't got a fly wire where shazza got us some strewth. She'll be right spit the dummy with it'll be fair go. We're going gobsmacked with as stands out like arvo. He's got a massive bush bash mate she'll be right slacker. "

4.  ACTUAL:    ""
4.  EXPECTED:  ""

my code:

var http = require('http');
var bl = require('bl');

var result = [];
var urls = process.argv.slice(2);
urls.forEach(function(url, i) {
  http.get(url, function(response) {
    response.pipe(bl(function(err, data) {
      if (err) return console.error(err);
      result[i] = data.toString();
      if (i === urls.length - 1) {
        console.log(result.join('\n'));
      }
    }));
  });
});

official solution:

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)

Basically the first test never passes (although if there is only 1 url in the iterated array (instead of 3), the first test passes but not the others). Any insight would be great. I'm not sure where to ask about this and perhaps I'm just missing some JS thing, so sorry if this is not appropriate.

like image 599
butterywombat Avatar asked Apr 06 '15 03:04

butterywombat


3 Answers

You haven't made sure that all of the urls have been downloaded.

The requests don't necessarily come back in order. Consider if 3 comes back first. You'll skip the other two urls and only print out 3.

The demo code counts the number of responses so it's guaranteed to get everything before it prints out the answer.

like image 157
mrmcgreg Avatar answered Oct 07 '22 11:10

mrmcgreg


I think that you just need wait until all requested results ends or any one error. There are my passed answer:

var http = require('http');
var bl = require('bl');

var urls = process.argv.slice(2)
var count = urls.length;

var results = [];

urls.forEach((url, index) => {
    http.get(url, (res) => {
        res.pipe(bl((err, data) => {
            if (err) throw err;

            results[index] = data.toString();
            count--;

            if (count == 0) {
                results.forEach((result) => {
                    console.log(result)
                });
            }
        }))
    })
})
like image 35
KCYun Avatar answered Oct 07 '22 11:10

KCYun


var http = require('http');

var links = [2, 3, 4];

var buffer = [];

(function render(index) {

http.get(process.argv[links[index]], function (response){

    response.setEncoding('utf8');

    response.on('data', function(chunk){
        if(buffer[index] === undefined) {
            buffer[index] = '';
        }
        buffer[index] += chunk;
    });
    response.on('end', function () {
        var newIndex = index+1;
        if(links[newIndex] !== undefined) {
            render(newIndex);
        } else {
            return renderOutput();
        }
    });
    response.on('error', console.error);

}).on('error', console.error);
})(0); //self-calling function

function renderOutput() {

buffer.forEach(function (elem) {

console.log(elem);

});
}
like image 30
MEMO H Avatar answered Oct 07 '22 11:10

MEMO H