Q:

Callback runs first? - learnyounode juggling

Can someone help me understand why my solution does not work? It seems like the callback function is running before the juggle function is finished. 
My code works fine if I remove the comments. It's just that I don't understand why the log function does not get called after the juggle function is finished. That is how callbacks are supposed to work right?
Thanks in advance :)
var http = require('http')
links = process.argv.slice(2)
var contents = []
//var cbacks = 0

function juggle(callback) {
    links.forEach(function(link, i, links) {
        http.get(link, function(response) {
            response.setEncoding("utf8")
            var str = ""
            response.on("data", function(data) {
                str = str.concat(data)
            })
            response.on("end", function(){
                contents[i] = str
                //cbacks++
                //if(cbacks === 3) {
                //  callback()
                //}
            })
        })
    })
    callback()
}

function log() {
    contents.forEach(function(content, i, contents) {
        console.log(contents[i])
    })
}

juggle(log)

A:

So you have global scope which is what I would use to actually juggle the requests.
When each link gets registered to an EventEmitter, you can store it inside of a map.
var link_map = {};
var request_counter = 0;

links.forEach( function (link, index) {
    link_map[link] = '';
...

then in your requests you can append data from a specific request 
 response.on('data', function (chunk) {
    link_map[link] += chunk.toString();
...

and finally at each end, check if all requests have finished
response.on('end', function () {
    request_counter += 1;
    if ( links.length === request_counter ) {
        // do your logging stuff here and you have all
        // the data that you need inside link_map
...

the link variable inside of the anonymous function declared in the forEach is stored for that closure. So each time that the 'data' event is emitted, the link variable is going to refer to the request for a specific link that was registered to the callback. That is why I chose to use a map data structure and map specific data to each link which we are using as a key.
EventEmitters and callbacks can get kind of harry if you are unfamiliar with them. Keep practicing though and it will eventually become easier.
And using an array as you did is not incorrect or anything, I just prefer to use Objects with key => value pairs when I can.
RUN THIS CODE on your machine to see it in action.
const http = require('http');

var links = [
        'http://www.google.com',
        'http://www.example.com',
        'http://www.yahoo.com'
];
var link_map = {};
var request_counter = 0;

links.forEach( function (link, index) {
    link_map[link] = '';

    http.get(link, function(response) {
        response.on('data', function (chunk) {
            link_map[link] += chunk.toString();
        });

        response.on('end', function () {
            request_counter += 1;
            if ( links.length === request_counter ) {
                links.forEach( function(link) {
                    require('fs').writeFileSync(link.split('//')[1],link_map[link]);
                });
            }
        });
    });
});

You can see an output of files from links in the parent directory.

