0

I create a small script to understand callback better.

From the below script, the behavior I expected was: "http.get runs and takes on average 200 ms. The for loop "i" increment takes on average 2500 ms. At 200 ms, the process should exit and the script should have stopped to work. Why is it printing all of i? If I understand this better, I think I understand callback.

var http = require("http");
var starttime = new Date();

//Function with Callback
for (var j =0; j<10; j++){
    http.get({host : 'nba.com'}, function(res){
        console.log("Time Taken = ", new Date() - starttime, 'ms');

        process.exit();
    }).on('error', function(er){
        console.log('Got Error :', er.message);
    })
}

//Loop that exceeds callback trigger time
for(var i=1; i<10000; i++){
    console.log(i);
}

console.log("Time Taken = ", new Date() - starttime, 'ms');
Pang
  • 9,564
  • 146
  • 81
  • 122
  • The for loop is synchronous and the code in it is asynchronous. It's running through the for loop firing the get async get call. The for loop exits before the on callbacks are fired. There's plenty of docs and samples on the internet to illustrate how async works. – bryanmac Aug 16 '16 at 04:12
  • Thanks bryanmac. I will check them out. Its clear as cloud now. – PatrickJames Aug 16 '16 at 11:49

1 Answers1

3

Javascript in node.js is single threaded and I/O is event driven using an event queue. Thus your async callbacks that signal the completion of the http requests cannot run until your original thread of Javascript finishes and returns control back to the system where it can then pull the next event from the event queue to service the completion of the http request.

As such, your for loop will run to completion before any http responses can be processed.

Here's the step by step process:

  1. Your first for loop runs and sends 10 http requests.
  2. These http requests run in the background using async networking. When one of them completes and has a response, the http module will put an event in the Javascript event queue and it will be the JS interpreter's job to pull that event from the event queue when it is finished with its other activities.
  3. Your second for loop runs to completion and all the i values are output to the console.
  4. Your script finishes.
  5. The JS interpreter then checks the event queue to see if there are any pending events. In this case, there will be some http response events. The JS interpreter pulls the oldest event from the event queue and calls the callback associated with that.
  6. When that callback finishes, the next event is pulled from the event queue and the process continues until the event queue is empty.
  7. If any of your callbacks call process.exit(), then this short circuits the remaining callbacks and exits the process immediately.

While this other answer was written for the browser, the event-driven, single threaded concept is the same as it is in node.js so this other answer may explain some more things for you: How does JavaScript handle AJAX responses in the background?

Community
  • 1
  • 1
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Thanks Jfiend00. That clearly explains it. The thing I forgot for network or I/O is async while CPU is sync due to single threaded. For loop is CPU related and no I/O. Makes sense. – PatrickJames Aug 16 '16 at 11:47