writeHead是非阻塞IO命令吗?

时间:2013-05-20 07:13:04

标签: node.js io synchronization

我正在编写一个代码来为客户端加载页面。一段代码是:

response.writeHead(301, {"Location": "/login/index.html"});
response.end("");

问题是,如果我有一个名为A的慢客户端,此代码是否会阻止其他客户端的事件循环?或者它可以在A等待加载页面时处理其他事件?

我在一本书中读到最好使用管道方法,如下面的代码:

var fs = require('fs');
var rs = fs.createReadStream('/login/index.html');
rs.pipe(response);

哪一个更好用?

3 个答案:

答案 0 :(得分:2)

不,writeHead不会启用I / O.它不能从网络/磁盘读取或写入。它只是写入响应(http.ServerResponse对象),它驻留在内存中。您创建/发送的每个响应都是一个单独的对象。每个响应只能调用一次,因此writeHead无法阻止。 http.ServerResponse实现了可写的Stream接口以进行同步。

要回答您的问题,它不能阻止客户端加载页面,与需要排序/序列化的SQL查询不同,writeHead需要进行简单的同步。

您已阅读的pipe()方法当然更好,但仅限于同步文件读取和较少的文件读取。如果您执行同步的readFileSync,将强制读取磁盘并阻止其余节点服务器的执行。因此,如果您使用它,则在读取文件时无法执行任何操作(执行一些有意义的操作)。

但是说你确实使用它。然后对于每个请求,文件将以异步方式从磁盘读取,但如果文件没有更改,则不需要这样做。将其读入内存然后将其用于进一步的请求是明智的。最好使用缓存,只有在磁盘上为静态文件更改时才执行只读。

因此最好使用像express那样的静态文件服务器。请参阅this

答案 1 :(得分:1)

不,writeHead不同步,它不会阻止事件循环。 我不建议在特定示例中使用管道。我有两个原因:

    作为静态文件的
  1. /login/index.html可以被缓存,从而降低网络传输。特别适用于慢速客户端连接。
  2. 一致性:登录网址始终相同。但这是一个品味问题:)

答案 2 :(得分:1)

正如@spotirca已经指出的那样,response.writeHead()没有被缓存,但我认为值得扩展到这个问题的另一个方面,即使用pipe()

pipe()实际上是一个红色鲱鱼,问题在于是重定向以使用现有的HTTP响应还是开始新的循环。重要的是要理解这两种解决方案做了很多不同的事情。

301重定向

response.writeHead(301, {"Location": "/login/index.html"});
response.end("");

这会通过永久重定向来响应浏览器,即告知浏览器当前网址应始终重定向到指定的网址。如果您根据会话状态将用户重定向到登录页面,那么这绝对是错误的,因为浏览器在缓存重定向并导致不良行为方面是合理的。

require('fs').createReadStream('/login/index.html').pipe(response);

这将工作,但这意味着登录页面将在当前网址上提供。您也可以通过在同一个URL上提供不同的内容来打破标准HTTP行为,因此@spotirca指出这会对缓存产生影响。

我的建议

使用302(临时)重定向到/login/,然后从那里提供内容。

response.writeHead(302, {"Location": "/login/"});
response.end("");

我从不在URL上包含文件扩展名,因为它会降低您以后更改内容的能力,但该方法的这一方面意味着您需要让请求处理程序侦听该URL并提供静态文件。您可以使用pipe()来设置合适的缓存标头,但我的建议是使用Express或类似的框架来避免与自定义代码相关的错误。

e.g。

// A framework will do most of this for you
response.writeHead("Expires","Thu, 01 Dec 2994 16:00:00 GMT"); 
require('fs').createReadStream('/login/index.html').pipe(response);