2

以下将无法正常工作:

var http = require('http');
var fs = require('fs');

var theIndex = fs.createReadStream('index.html');

http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/html'});
    theIndex.pipe(res);
}).listen(9000);

它在第一次请求时会很好,但对于所有后续请求,不会将 index.html 发送到客户端。createReadStream 调用似乎需要在 createServer 回调中。我想我可以概念化为什么,但你能用语言表达为什么吗?似乎一旦流完成,文件句柄就会关闭,并且必须再次创建流?它不能简单地“重新启动”吗?这个对吗?

谢谢

4

1 回答 1

5

流包含跟踪流状态的内部状态——在文件流的情况下,您有一个文件描述符对象一个读取缓冲区以及文件已被读取到的当前位置。因此,“倒带”一个 Node.js 流是没有意义的,因为 Node.js 是一个异步环境——这是需要牢记的重要一点,因为这意味着两个 HTTP 请求可以在中间同时处理。

如果一个 HTTP 请求导致流开始从磁盘流式传输,并且在流式传输过程中途另一个HTTP 请求进入,则无法在第二个 HTTP 请求中使用相同的流(内部记录保存将错误地发送第二个 HTTP 响应错误的数据)。同样,在处理第二个 HTTP 请求时回退流会导致错误的数据被发送到原始HTTP 请求。

如果 Node.js不是一个异步环境,并且在你倒带之前保证流完全用完,那么倒带流可能是有意义的(尽管还有其他考虑因素,例如open, end, 和close事件)。

您确实可以访问低级fs.read机制,因此理论上您可以创建一个仅打开单个文件描述符但生成多个流的 API;每个流都包含自己的缓冲区和读取位置,但共享一个文件描述符。也许是这样的:

var http = require('http');
var fs = require('fs');

var theIndexSpawner = createStreamSpawner('index.html');

http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/html'});
    theIndexSpawner.spawnStream().pipe(res);
}).listen(9000);

当然,你必须弄清楚什么时候应该关闭文件描述符,确保你不会持有它太久,等等。除非你发现多次打开文件是你应用程序的实际瓶颈,这可能不值得精神开销。

于 2013-09-11T22:46:04.363 回答