可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
How to close a readable stream in Node.js?
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.");
}
});
This would be better than:
input.on('data', function(data) {
if (isEnded) { return; }
if (gotFirstLine) {
isEnded = true;
console.log("Closed.");
}
});
But this would not stop the reading process...
回答1:
Invoke input.close()
. It's not in the docs, but
https://github.com/joyent/node/blob/cfcb1de130867197cbc9c6012b7e84e08e53d032/lib/fs.js#L1597-L1620
clearly does the job :) It actually does something similar to your isEnded
.
EDIT 2015-Apr-19 Based on comments below, and to clarify and update:
- This suggestion is a hack, and is not documented.
- Though for looking at the current
lib/fs.js
it still works >1.5yrs later.
- I agree with the comment below about calling
destroy()
being preferable.
- As correctly stated below this works for
fs
ReadStreams
's, not on a generic Readable
As for a generic solution: it doesn't appear as if there is one, at least from my understanding of the documentation and from a quick look at _stream_readable.js
.
My proposal would be put your readable stream in paused mode, at least preventing further processing in your upstream data source. Don't forget to unpipe()
and remove all data
event listeners so that pause()
actually pauses, as mentioned in the docs
回答2:
ReadStream.destroy
You can call the ReadStream.destroy function at any time.
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');
});
The public function ReadStream.destroy
is not documented (Node.js v0.12.2) but you can have a look at the source code on GitHub (Oct 5, 2012 commit).
The destroy
function internally mark the ReadStream
instance as destroyed and calls the close
function to release the file.
You can listen to the close event to know exactly when the file is closed. The end event will not fire unless the data is completely consumed.
Note that the destroy
(and the close
) functions are specific to fs.ReadStream. There are not part of the generic stream.readable "interface".
回答3:
Today, in Node 10
readableStream.destroy()
is the official way to close a readable stream
see https://nodejs.org/api/stream.html#stream_readable_destroy_error
回答4:
You can't. There is no documented way to close/shutdown/abort/destroy a generic Readable stream as of Node 5.3.0. This is a limitation of the Node stream architecture.
As other answers here have explained, there are undocumented hacks for specific implementations of Readable provided by Node, such as fs.ReadStream. These are not generic solutions for any Readable though.
If someone can prove me wrong here, please do. I would like to be able to do what I'm saying is impossible, and would be delighted to be corrected.
EDIT: Here was my workaround: implement .destroy()
for my pipeline though a complex series of unpipe()
calls. And after all that complexity, it doesn't work properly in all cases.
回答5:
At version 4.*.*
pushing a null value into the stream will trigger a EOF
signal.
From the nodejs docs
If a value other than null is passed, The push() method adds a chunk of data into the queue for subsequent stream processors to consume. If null is passed, it signals the end of the stream (EOF), after which no more data can be written.
This worked for me after trying numerous other options on this page.
回答6:
You can clear and close the stream with yourstream.resume()
, which will dump everything on the stream and eventually close it.
From the official docs:
readable.resume():
Return: this
This method will cause the readable stream to resume emitting 'data' events.
This method will switch the stream into flowing mode. If you do not want to consume the data from a stream, but you do want to get to its 'end' event, you can call stream.resume() to open the flow of data.
var readable = getReadableStreamSomehow();
readable.resume();
readable.on('end', () => {
console.log('got to the end, but did not read anything');
});
回答7:
It's an old question but I too was looking for the answer and found the best one for my implementation. Both end
and close
events get emitted so I think this is the cleanest solution.
This will do the trick in node 4.4.* (stable version at the time of writing):
var input = fs.createReadStream('lines.txt');
input.on('data', function(data) {
if (gotFirstLine) {
this.end(); // Simple isn't it?
console.log("Closed.");
}
});
For a very detailed explanation see:
http://www.bennadel.com/blog/2692-you-have-to-explicitly-end-streams-after-pipes-break-in-node-js.htm
回答8:
This destroy module is meant to ensure a stream gets destroyed, handling different APIs and Node.js bugs. Right now is one of the best choice.
NB. From Node 10 you can use the .destroy
method without further dependencies.
回答9:
This code here will do the trick nicely:
function closeReadStream(stream) {
if (!stream) return;
if (stream.close) stream.close();
else if (stream.destroy) stream.destroy();
}
writeStream.end() is the go-to way to close a writeStream...