After playing with Node.js and reading about async i/o & evented programming a lot I'm left with some question marks.
Consider the following (pseudo) code:
var http = require('http');
function onRequest(request, response)
{
// some non-blocking db query
query('SELECT name FROM users WHERE key=req.params['key']', function (err, results, fields) {
if (err) {
throw err;
}
username = results[0];
});
// some non-blocking db query
query('SELECT name FROM events WHERE key=req.params['key']', function (err, results, fields) {
if (err) {
throw err;
}
event_name = results[0];
});
var body = renderView(username, event_name, template);
res.writeHead(200, {'Content-Type': 'text/plain'});
res.write(body);
res.end();
};
http.createServer(onRequest).listen(8888);
// request A: http://127.0.0.1:1337/?key=A
// request B: http://127.0.0.1:1337/?key=B
(I think) I understand the basics of the event loop; With libev, Node.js creates an event loop that polls (epoll/kqueue/...) a bunch of file descriptors to see if any events are triggered (new connection, writable, data available etc). If there is a new request the event loop calls the anonymous function passed to createServer. What I don't understand is what happens after:
1) To run the queries concurrently the db driver has to have some kind of threading/connection pool, right?
2) In the scope of one request: What happens after sending two queries? renderView can't be called because the queries have not returned yet. How do we wait for the queries to return? Should it keep count of the callbacks pending to be fired before continuing? The basic thought I had was;
onRequest -> run async code -> wait for callbacks -> construct response. The waiting in this case would be blocking so you would effectively need to spawn a thread for each onRequest. How is the "waiting for callbacks to run before constructing response" done?
3) How does the db driver inform the event-loop that it's done and the callback it has for it needs to be called with the query results?
4) How does the event loop run the callback inside the anonymous function we created with the onRequest event? Is this where the closure concept comes in where the context is "saved" in the callback function?
4) Now that we have the db results, how do we continue executing the renderView/res.write/res.end
parts?