2017-03-04 16 views
1

完整的node.js初学者在这里。我看到这个“Hello World”示例地方节点js中的请求响应周期如何与外部I/O配合工作

// Load the http module to create an http server. 
var http = require('http'); 

// Configure our HTTP server to respond with Hello World to all requests. 
var server = http.createServer(function (request, response) { 
    response.writeHead(200, {"Content-Type": "text/plain"}); 
    response.end("Hello World\n"); 
}); 

// Listen on port 8000, IP defaults to 127.0.0.1 
server.listen(8000); 

// Put a friendly message on the terminal 
console.log("Server running at http://127.0.0.1:8000/"); 

真正简单的代码在服务器响应HTTP与纯文本的简单的HTTP响应请求的“Hello World”

我也准备约库从javascript发出HTTP请求

http.get(options, function(resp){ 
    resp.on('data', function(chunk){ 
    //do something with chunk 
    }); 
}).on("error", function(e){ 
    console.log("Got error: " + e.message); 
}); 

在这里,您使用某些选项创建HTTP请求,然后在回调中执行某些操作。

如果有人在HTTP请求到达node.js服务器时发出这样的API请求,会发生什么?由于流必须是单线程的,因此如何改变响应的状态node.js在HTTP API请求的回调中发送给客户端?那么到时候已经不会将响应发送到事件循环了吗?如何模拟此系统中的同步请求,以便您可以使用API​​请求的响应向客户端发送响应?

回答

3

由于流必须是单线程的,所以如何改变响应的状态node.js在HTTP API请求的回调中发送给客户端?

因为响应没有与接收到的请求同步发送。

到那时,响应是否会被发送到事件循环?

响应不发送,直到调用res.send或类似的,这并不一定是从触发了您的请求,回调作业队列中的同一个作业  —,经常是没有的。

如何模拟此系统中的同步请求,以便您可以使用API​​请求的响应向客户端发送响应?

有没有必要,这样做会杀死吞吐量。

在任何给定的线程上(和NodeJS只使用一个),JavaScript的工作原理是基于作业队列:单个JavaScript线程通过从队列中拾取作业,一直运行代码通过,然后从队列中提取下一个作业(或空转直到添加一个作业)。当事件进入或类似时,如果您为该事件设置了处理程序,则将对处理程序的调用添加到作业队列中。 (实际上至少有两层到作业队列;如果您有兴趣,请参阅this answer以获取更多信息。)

如果您不响应“我们已获得HTTP请求”调用处理程序的作业的代码。这很正常。工作和请求完全相互分离。所以如果你启动了一个异步进程(比如get,或者readFile),那很好(也是正常的)。稍后,当该进程的结果可用时,新作业将被添加到队列中,JavaScript线程将其拾取,并使用res.send或类似的方法来回复正在等待的请求。

这就是NodeJS如何管理高吞吐量,尽管只有一个线程:如果你在整个过程中使用异步I/O,实际的代码不必占用线程,因为它不会等待完成I/O。当I/O挂起时,它可以在其他事情上做更多的工作,然后在I/O完成时做出响应。