Reputation: 4187
Can someone take me through what's happening with all the callbacks here? I'm new to Node and am lost! I have commented some sources of confusion below.
var utils = require('./utils');
"POST": function(request, response) {
//collect the data
utils.collectData(request, function(message) {
message.objectID = ++objectIDcounter;
messages.push(message);
utils.sendResponse(response, {
objectID: message.objectID
}, 201)
})
}
// this is in utils.js:
//why is a callback parameter passed to this function?
exports.collectData = function(request, callback) {
var data = ""
request.on('data', function(chunk) {
data += chunk;
})
request.on('end', function() {
//why is the callback applied here?
//Also, we are parsing the data here. why? because it is a buffer or a string here?
callback(JSON.parse(data));
})
}
Upvotes: 1
Views: 141
Reputation: 707218
why is a callback parameter passed to this function?
request.on()
installs an event handler that will be called some time LATER (e.g. some arbitrary time in the future). The .collectData()
method will return before that event handler is called.
So, the only want to communicate back the results of all the data that was collected is to call a callback when the request.on('end', ...)
event handler signals that all the data has now been collected.
Let's instrument this with log statements and perhaps this will give you an idea how the sequence of events works:
console.log("before collectData()");
utils.collectData(request, function(message) {
console.log("in collectData() callback");
message.objectID = ++objectIDcounter;
messages.push(message);
utils.sendResponse(response, {
objectID: message.objectID
}, 201)
})
}
console.log("after collectData()");
// this is in utils.js:
//why is a callback parameter passed to this function?
exports.collectData = function(request, callback) {
console.log("in collectData() method");
var data = ""
request.on('data', function(chunk) {
console.log("in request.on('data', ...)");
data += chunk;
})
request.on('end', function() {
console.log("in request.on('end', ...)");
callback(JSON.parse(data));
})
}
With those console.log()
statements, you would get this sequence in the debug console:
before collectData()
in collectData() method
after collectData()
in request.on('data', ...)
in request.on('data', ...)
in request.on('data', ...)
in request.on('end', ...)
in collectData() callback
You can see that the collectData()
runs and finishes, but the event handlers are still in place as, as the incoming data arrives, they do their work and then finally when the 'end'
event arrives, all the data has finished arriving and the callback can be called to communicate back the final accumulation of data.
This is the asynchronous nature of I/O in node.js. You start an operation, set up some listeners or callbacks and then the node.js libraries use various OS services to carry out the actual I/O operation in the background. Meanwhile other node.js code can continue to run and then sometime later, the I/O operation will finish and insert an event in the node.js event queue. When the current JS thread of execution finishes doing whatever it is doing, the node.js engine will pull the next event off the event queue and fire whichever callback is associated with that event, allowing some node.js code to service that event. The creators of node.js refer to this as "evented I/O".
Though this answer was written for the browser, the concepts of an event queue and how it is used and managed are identical in node.js so this answer may help you understand better: How does JavaScript handle AJAX responses in the background? and an article that also may help: Understanding the node.js event loop.
why is the callback applied here?
When the 'end'
event is received that tells the code that all data has now been received. There will not be any more 'data'
events for this request. At that point, you know that you now have all the data so that's the place that the callback is called with the final accumulation of data.
Also, we are parsing the data here. why? because it is a buffer or a string here?
I can't at the moment find the documentation for collectData()
, but it appears that it is expecting a JSON string to be the data so it is parsing that JSON string so it can return the corresponding Javascript object.
Upvotes: 3