How does the Node.js event loop work?

2020-05-21 05:14发布

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?

2条回答
倾城 Initia
2楼-- · 2020-05-21 05:38

Run parrallel async code pattern:

To 'Wait for result from both async functions' you can do: in both async calls callbacks check both result and if all ready, call your DoSomethingWithTwoDependantResults.

In your example you probably need to execute queries sequentially:

query(sql1, function(sqlres1) {
    query(sql2, function(sqlres2) {
        writeResultUsingDataFrom(sqlres1, sqlres2);
    }
});

your original code, modified to execute two queries in parallel:

function writeReply(res, template, username, event_name)
{
    var body = renderView(username, event_name, template);
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.write(body);
    res.end();
} 

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];
        if (username && event_name)
            writeReply(res, template, username, event_name);
    });

    // 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];
        if (username && event_name)
            writeReply(res, template, username, event_name);

    });
};
查看更多
成全新的幸福
3楼-- · 2020-05-21 05:40

Have you seen this? I'm still getting the hang of it all and I can't answer your question in detail, but basically you're right about the thread-pool... Ryan explains quite a lot in the video.

EDIT: And this one from about a year later, when he goes into more detail.

查看更多
登录 后发表回答