nodeschool / discussions

:school::speech_balloon: need help with nodeschool? or just wanna ask a question? open an issue on this repo!
489 stars 107 forks source link

aync juuggling - can't explain behaiviour #1697

Closed swinston100 closed 8 years ago

swinston100 commented 8 years ago

This is about Juggling Async in Learnyounode (Exercise 9 of 13)

I have the program working by changing the location of

if(count==3) printResults();

If it's located in the bl function then it works but I move this code outside that function then the count never reaches 3. Can someone please explain to a relative beginner why this is.

The code below contains a console.log() so that I could determine the count as the program ran. This is why I am getting output 0,1,2... :-)

Thanks!

var http = require('http');
var bl = require('bl');
var results = [];
var count = 0;
for (var i = 0; i < 3; i++)
  httpGet(i)

function httpGet(index) {

  http.get(process.argv[index+2], function(response){
    response.pipe(bl(function(err,data){
      results[index] = data.toString();
      count++

      // works here - comment to get working
      //if(count==3){ printResults(); }

    }));

        console.log('count: ' + count);
        // doesn't work here
        if(count==3){ printResults(); }

  });

}

function printResults () {
  for (var i = 0; i < 3; i++)
    console.log(results[i]);
  }
hackergrrl commented 8 years ago

Let's flatten out your httpGet function and its two callback functions into three distinct functions:

function httpGet(index) {
  http.get(process.argv[index+2], handleResponse)
}

function handleResponse(response){
    response.pipe(bl(handleData))
}

function handleData(err,data){
      results[index] = data.toString();
      count++

      // (A)
      if(count==3){ printResults(); }
}

// (B)
if(count==3){ printResults(); }

Where control flows from httpGet -> handleResponse -> handleData each timehttpGet is called.

This is a bit more intuitive to think about -- many nested callbacks can obfuscate the control flow. (B) is actually executed before the code in any of these functions is: http.get() triggers an asynchronous process that will result in handleResponse being called at some point in the future.

swinston100 commented 8 years ago

Many thanks @noffle for making my code more understandable and for the great explanation :-) :+1: