0

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

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

哪个更好用?

4

3 回答 3

2

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

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

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

但是说你确实使用它。然后对于每个请求,文件都将从磁盘异步读取,但如果文件没有更改,这将变得不必要。一次将其读入内存然后将其用于进一步的请求是明智的。最好使用仅在静态文件在磁盘上发生更改时才执行读取的缓存。

所以最好使用静态文件服务器express。看到这个

于 2013-05-20T18:39:04.040 回答
1

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

  1. /login/index.html,作为静态文件,可以缓存,因此降低了网络传输。尤其适用于慢速客户端连接。
  2. 一致性:登录 url 始终相同。但这是一个口味问题:)
于 2013-05-20T07:30:54.370 回答
1

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

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

301重定向

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

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

流媒体

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

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

我的建议

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

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

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

例如

// 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);
于 2013-05-20T11:14:32.743 回答