First, lets take out the anonymous function and make it a regular function:
var http = require('http');
function serverCallback(req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
}
http.createServer(serverCallback).listen(8080);
Here you can see that the code is calling http.createServer()
and passing one argument which is a function reference.
Per the documentation for http.createServer()
, when it calls that callback, it will pass two arguments to that function. The first argument is the request
object, the second argument is the response
object. So, when we declare our callback function, we declare and name those two arguments to our callback so that we can properly use the arguments that are sent to it.
A common point of confusion with Javascript callbacks is that it is the http.createServer()
function that decides what arguments to pass this callback and we MUST declare our callback arguments to match what the host function will pass to it. Those arguments names are just convenient programming names that we can use to refer to the two arguments - what we call them does not influence what is actually passed there. So, we must pick names that match what the http.createServer()
function is actually passing to the callback.
So, now that you see how the basic callback works, the named function serverCallback
can be put inline like this:
var http = require('http');
http.createServer(function serverCallback(req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
}).listen(8080);
I've literally just take the top definition of serverCallback and placed it inline. Note, it even still has the function name. This will work just fine too. But, we aren't really using the serverCallback
name so it is isn't needed. That can be removed to end up with this:
var http = require('http');
http.createServer(function(req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
}).listen(8080);
This is now an inline anonymous function declaration. It's the same as a regular function declaration, it's just declared inline and the function name is optional.
Now, for your specific questions:
I understand that the function (req, res) part is the "anonymous
function" which is what is executing the callback function. But I
don't know HOW and WHY. Why is the keyword to do this "function", and
where are those parameters from?
function
is how you declare a function. This is declaring a function inline so the function
keyword is still needed. The parameters are described in my explanation above. They are declared only as convenient monikers for us to use in our code to match what http.createServer()
will pass the callback when it calls it. req
is a request object and res
is a response object and both have their own pages in the node.js documentation as they have both properties and methods.
I still haven't come across a good explanation for how this works. I get how it works at a high abstract metaphorical level but I don't understand what the code means.
Let me know if my above explanation leaves you with any further questions on how the code works.
What I don't understand is some of the syntax and HOW the code
actually gets this to work.
If, what you're asking here is how does Javascript call this callback each time some server event happens, then that's a bit of a longer conversation. Behind http.createServer()
is some native code that sets up a server. At the TCP level, it defines an incoming port that is listening for new connections on. When one of those new connections occurs (someone from the outside establishes a connection to your server), then the OS services will notify the native code behind this http server that a new incoming connection has been established (e.g. there's a new TCP socket now connected and an HTTP request has been sent over that socket). The native code behind this will then add an event and some data to the Javascript event queue.
If the current JS interpreter is not currently running, then adding something to the event queue will trigger a callback for that event and it will create the appropriate arguments and call the associated callback, executing whatever code you registered as the callback. If the JS engine was currently running some other JS code, then the event will sit in the JS event queue until the current JS thread finishes executing. At that point the JS engine will pull the next event out of the event queue and execute it (calling its callback).
For more about the general concept of the event queue, you can read these other posts:
How does JavaScript handle AJAX responses in the background?
Where is the node.js event queue?