在玩过 Node.js 并阅读了很多关于异步 i/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 创建了一个事件循环,轮询(epoll/kqueue/...)一堆文件描述符,以查看是否触发了任何事件(新连接、可写、数据可用等)。如果有新请求,事件循环调用传递给 createServer 的匿名函数。我不明白的是之后会发生什么:
1)要同时运行查询,数据库驱动程序必须有某种线程/连接池,对吗?
2)在一个请求的范围内:发送两个查询后会发生什么?无法调用 renderView,因为查询尚未返回。我们如何等待查询返回?它是否应该在继续之前保留待触发的回调计数?我的基本想法是;
onRequest -> 运行异步代码 -> 等待回调 -> 构造响应。在这种情况下,等待将是阻塞的,因此您实际上需要为每个 onRequest 生成一个线程。“在构建响应之前等待回调运行”是如何完成的?
3) db 驱动程序如何通知事件循环它已经完成并且它所具有的回调需要与查询结果一起调用?
4) 事件循环如何在我们使用 onRequest 事件创建的匿名函数中运行回调?这是闭包概念出现在回调函数中“保存”上下文的地方吗?
4) 现在我们有了 db 结果,我们如何继续执行这些renderView/res.write/res.end
部分?