Node.js事件循环如何工作?

在玩了Node.js并阅读了很多关于asynchronousI / O和编程的事情之后,我留下了一些问号。

考虑以下(伪)代码:

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 

(我认为)我理解事件循环的基础知识; 使用libev,Node.js创build一个事件循环,轮询(epoll / kqueue / …)一堆文件描述符以查看是否触发了任何事件(新连接,可写,可用数据等)。 如果有新的请求,则事件循环会调用传递给createServer的匿名函数。 我不明白的是:

1)为了同时运行查询,db驱动程序必须具有某种线程/连接池,对吧?

2)在一个请求的范围内:发送两个查询后会发生什么? 查询不能被调用,因为查询还没有返回。 我们如何等待查询返回? 在继续之前是否应该保留待解决的callback计数? 我的基本思想是,

onRequest – >运行asynchronous代码 – >等待callback – >构build响应。 在这种情况下,等待会被阻塞,所以你需要为每个onRequest生成一个线程。 “构build响应之前等待callback运行”是如何完成的?

3)数据库驱动程序如何通知事件循环,它已完成,它的callback需要与查询结果一起调用?

4)事件循环如何在我们使用onRequest事件创build的匿名函数中运行callback? 这是封闭的概念来到哪里上下文被“保存”在callback函数?

4)现在我们有了db结果,我们该如何继续执行renderView/res.write/res.end部分?

运行并行asynchronous代码模式:

要“等待来自两个asynchronous函数的结果”,您可以执行以下操作:在两个asynchronous调用callback中,检查结果,如果准备就绪,请调用DoSomethingWithTwoDependantResults。

在你的例子中,你可能需要按顺序执行查询:

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

您的原始代码,修改为并行执行两个查询:

 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); }); }; 

你见过这个吗? 我仍然掌握了这一切,我不能详细回答你的问题,但基本上你是正确的关于线程池… Ryan在video中解释了很多。

编辑: 这一个从大约一年后,当他进入更多的细节。