如何关闭可读流(结束前)?

时间:2013-10-09 16:04:41

标签: node.js stream fs

如何关闭Node.js中的readable stream

var input = fs.createReadStream('lines.txt');

input.on('data', function(data) {
   // after closing the stream, this will not
   // be called again

   if (gotFirstLine) {
      // close this stream and continue the
      // instructions from this if
      console.log("Closed.");
   }
});

这比以下更好:

input.on('data', function(data) {
   if (isEnded) { return; }

   if (gotFirstLine) {
      isEnded = true;
      console.log("Closed.");
   }
});

但这不会阻止阅读过程......

9 个答案:

答案 0 :(得分:51)

编辑:好消息!从Node.js 8.0.0 readable.destroy开始正式提供:https://nodejs.org/api/stream.html#stream_readable_destroy_error

ReadStream.destroy

您可以随时调用ReadStream.destroy功能。

var fs = require('fs');

var readStream = fs.createReadStream('lines.txt');
readStream
    .on('data', function (chunk) {
        console.log(chunk);
        readStream.destroy();
    })
    .on('end', function () {
        // This may not been called since we are destroying the stream
        // the first time 'data' event is received
        console.log('All the data in the file has been read');
    })
    .on('close', function (err) {
        console.log('Stream has been destroyed and file has been closed');
    });

未记录公共函数ReadStream.destroy(Node.js v0.12.2),但您可以查看source code on GitHubOct 5, 2012 commit)。

destroy函数在内部将ReadStream实例标记为已销毁,并调用close函数以释放该文件。

您可以收听close event以确切知道文件何时关闭。除非数据被完全消耗,否则end event不会触发。

请注意,destroy(以及close)函数特定于fs.ReadStream。通用stream.readable“接口”没有部分。

答案 1 :(得分:29)

调用input.close()。它不在文档中,而是

https://github.com/joyent/node/blob/cfcb1de130867197cbc9c6012b7e84e08e53d032/lib/fs.js#L1597-L1620

显然可以完成工作:)它实际上与您的isEnded类似。

编辑2015年4月19日根据以下评论,澄清并更新:

  • 这个建议是黑客攻击,没有记录。
  • 虽然查看当前的lib/fs.js,但仍然可以使用1.5小时。
  • 我同意以下有关致电destroy()更优先的评论。
  • 如下所述,这适用于fs ReadStreams,而不适用于通用Readable

至于通用解决方案:它似乎没有一个,至少从我对文档的理解和快速查看_stream_readable.js开始。

我的建议是将您的可读流放入暂停模式,至少可以阻止您在上游数据源中进一步处理。不要忘记unpipe()并删除所有data个事件监听器,以便pause()实际暂停,如the docs

中所述

答案 2 :(得分:15)

今天,在节点10

HexCell

是关闭可读流的官方方式

请参阅https://nodejs.org/api/stream.html#stream_readable_destroy_error

答案 3 :(得分:11)

你不能。从Node 5.3.0开始,没有记录的关闭/关闭/中止/销毁通用Readable流的方法。这是节点流体系结构的限制。

正如此处的其他答案所解释的那样,Node提供的Readable的具体实现还有未记录的hack,例如fs.ReadStream。这些不是任何Readable的通用解决方案。

如果有人在这里证明我错了,请这样做。我希望能够做到我所说的不可能,并且很乐意得到纠正。

编辑:以下是我的解决方法:implement .destroy() for my pipeline though a complex series of unpipe() calls.在完成所有这些复杂性后,doesn't work properly in all cases

答案 4 :(得分:10)

在版本4.*.*将空值推入流中会触发EOF信号。

来自nodejs docs

  

如果传递了null以外的值,则push()方法将一大块数据添加到队列中,供后续流处理器使用。如果传递null,则表示流的结尾(EOF),之后不能再写入数据。

在此页面上尝试了许多其他选项后,这对我有用。

答案 5 :(得分:4)

这个destroy模块旨在确保流被破坏,处理不同的API和Node.js错误。现在是最好的选择之一。

NB。从节点10,您可以使用.destroy方法,而无需进一步依赖。

答案 6 :(得分:3)

您可以使用yourstream.resume()清除和关闭流,这将转储流上的所有内容并最终将其关闭。

来自official docs

  

readable.resume():

     

返回:这个

     

此方法将使可读流恢复发送数据'事件

     

此方法将流切换为流动模式。如果您不想使用流中的数据,但您确实想要使用它的结尾' event,您可以调用stream.resume()来打开数据流。

var readable = getReadableStreamSomehow();
readable.resume();
readable.on('end', () => {
  console.log('got to the end, but did not read anything');
});

答案 7 :(得分:3)

这是一个老问题,但我也在寻找答案,并为我的实施找到了最好的答案。 endclose事件都会被发出,所以我认为这是最干净的解决方案。

这将在节点4.4中起作用。*(写作时的稳定版本):

var input = fs.createReadStream('lines.txt');

input.on('data', function(data) {
   if (gotFirstLine) {
      this.end(); // Simple isn't it?
      console.log("Closed.");
   }
});

有关详细说明,请参阅: http://www.bennadel.com/blog/2692-you-have-to-explicitly-end-streams-after-pipes-break-in-node-js.htm

答案 8 :(得分:2)

这里的代码很好地解决了这个问题:

function closeReadStream(stream) {
    if (!stream) return;
    if (stream.close) stream.close();
    else if (stream.destroy) stream.destroy();
}

writeStream.end()是关闭writeStream的首选方法......