Handling multiple call asynchronous callbacks

asynchronous, javascript, node.js

Solution

This is how I would go about solving the problem.

#!/usr/bin/env node

var http = require('http');
var argv = process.argv.splice(2),
    truecount = argv.length,
    pages = [];

function printUrls() {
  if (--truecount > 0)
    return;
  for (i = 0; i < pages.length; i++) {
    console.log(pages[i].data + '\n\n');
  }
}

function HTMLPage(url) {
  var _page = this;
  _page.data = '### [URL](' + url + ')\n';
  http.get(url, function(res) {
    res.setEncoding('utf8');
    res.on('data', function(data) {
      _page.data += data;
    });
    res.on('end', printUrls);
  });
}


for (var i = 0; i < argv.length; i++)
  pages.push(new HTMLPage(argv[i]));

It adds the requests to an array on the start of each request, that way once done I can iterate nicely through the responses knowing that they are in the correct order.

When dealing with asynchronous processing, I find it much easier to think about each process as something with a concrete beginning and end. If you require the order of the requests to be preserved then the entry must be made on creation of each process, and then you refer back to that record on completion. Only then can you guarantee that you have things in the right order.

If you were desperate to use your above method, then you could define a variable inside your get callback closure and use that to store the urls, that way you wouldn't end up with the last url overwriting your variables. If you do go this way though, you'll dramatically increase your overhead when you have to use your urls from process.argv to access each response in that order. I wouldn't advise it.

Problem

I am learning node.js with `learnyounode`. I am having a problem with `JUGGLING ASYNC`. The problem is described as follows: You are given three urls as command line arguments. You are supposed to make `http.get()` calls to get data from these urls and then print them in the same order as their order in the list of arguments. Here is my code: ``` var http = require('http') var truecount = 0; var printlist = [] for(var i = 2; i < process.argv.length; i++) { http.get(process.argv[i], function(response) { var printdata = ""; response.setEncoding('utf8'); response.on('data', function(data) { printdata += data; }) response.on('end', function() { truecount += 1 printlist.push(printdata) if(truecount == 3) { printlist.forEach(function(item) { console.log(item) }) } }) }) } ``` Here is the questions I do not understand: I am trying to store the completed data in `response.on('end', function(){})`for each url using a dictionary. However, I do not know how to get the url for that `http.get()`. If I can do a local variable inside `http.get()`, that would be great but I think whenever I declare a variable as `var url`, it will always point to the last url. Since it is global and it keeps updating through the loop. What is the best way for me to store those completed data as the value with the key equal to the url?

Original source