问题
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');
回答1:
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:
- Your first
for
loop runs and sends 10 http requests. - 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.
- Your second
for
loop runs to completion and all thei
values are output to the console. - Your script finishes.
- 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.
- When that callback finishes, the next event is pulled from the event queue and the process continues until the event queue is empty.
- 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?
来源:https://stackoverflow.com/questions/38966259/understanding-call-backs