Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I close ReadStream after using .pipe() method

Tags:

node.js

I'm reading file using FS#createReadStream method, then piping it to some writable streams using #pipe() method. Like this:

const stream = fs.createReadStream(...);
const transformedStream = imgStream.pipe(someTransformer).pipe(anotherTransfomer);
// do something with transformedStream

In docs of #createReadStream() method I found that it has autoClose parameter set by default to true.

And from other side, I found this in documentation of #pipe() method:

One important caveat is that if the Readable stream emits an error during processing, the Writable destination is not closed automatically. If an error occurs, it will be necessary to manually close each stream in order to prevent memory leaks.

So I have 2 questions:

  1. Should I close readable and writable streams in Node JS at all? (Manually, using the try-finally block). Or streams closed automatically?

  2. or should I close streams only and only when I'm using #pipe() method? ( because #pipe() can result to memory leaks)

like image 989
WelcomeTo Avatar asked Apr 04 '17 08:04

WelcomeTo


1 Answers

If you are using the pipe event, then you can use unpipe to end it.

Below is an example of using pipe(), and unpipe() event.

const writer = getWritableStreamSomehow();
const reader = getReadableStreamSomehow();
writer.on('unpipe', (src) => {
  console.error('Something has stopped piping into the writer.');
  assert.equal(src, reader);
});
reader.pipe(writer);
reader.unpipe(writer);

According to node.js documentation, The 'unpipe' event is emitted when the stream.unpipe() method is called on a Readable stream, removing this Writable from its set of destinations.

To specifically address your questions, here are my thoughts:

1) Should I close readable and writable streams in Node JS at all? (Manually, using the try-finally block). Or streams closed automatically?

2) or should I close streams only and only when I'm using #pipe() method? ( because #pipe() can result to memory leaks)

You must close your stream(s) no matter you are using pipe() or not. (Also I disagree with your comment about memory leakage issue if using pipe() only )

Also you can't close your stream in a traditional javascript try() catch() finally() clause. Reason is because the read and write stream are being executed asynchronously. Instead you have to emit the end event for them.

example:

var readStream = getReadableStreamSomehow();
readStream
    .on('data', function (chunk) {
        console.log(chunk);
    })
    .on('end', function () {
        console.log('All the data in the file has been read');
    })
    .on('close', function (err) {
        console.log('Stream has been Closed');
    });

You can emit the same events for writable stream.

like image 94
Benjamin Avatar answered Oct 08 '22 10:10

Benjamin