我正在编写一个代码来为客户端加载页面。一段代码是:
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);
哪一个更好用?
答案 0 :(得分:2)
不,writeHead
不会启用I / O.它不能从网络/磁盘读取或写入。它只是写入响应(http.ServerResponse对象),它驻留在内存中。您创建/发送的每个响应都是一个单独的对象。每个响应只能调用一次,因此writeHead
无法阻止。 http.ServerResponse
实现了可写的Stream接口以进行同步。
要回答您的问题,它不能阻止客户端加载页面,与需要排序/序列化的SQL查询不同,writeHead
需要进行简单的同步。
您已阅读的pipe()方法当然更好,但仅限于同步文件读取和较少的文件读取。如果您执行同步的readFileSync
,将强制读取磁盘并阻止其余节点服务器的执行。因此,如果您使用它,则在读取文件时无法执行任何操作(执行一些有意义的操作)。
但是说你确实使用它。然后对于每个请求,文件将以异步方式从磁盘读取,但如果文件没有更改,则不需要这样做。将其读入内存然后将其用于进一步的请求是明智的。最好使用缓存,只有在磁盘上为静态文件更改时才执行只读。
因此最好使用像express
那样的静态文件服务器。请参阅this。
答案 1 :(得分:1)
不,writeHead
不同步,它不会阻止事件循环。
我不建议在特定示例中使用管道。我有两个原因:
/login/index.html
可以被缓存,从而降低网络传输。特别适用于慢速客户端连接。答案 2 :(得分:1)
正如@spotirca已经指出的那样,response.writeHead()
没有被缓存,但我认为值得扩展到这个问题的另一个方面,即使用pipe()
。
pipe()
实际上是一个红色鲱鱼,问题在于是重定向以使用现有的HTTP响应还是开始新的循环。重要的是要理解这两种解决方案做了很多不同的事情。
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);