14 Oct
2013

Detecting the End of a Rainbow Inside a Writable Stream

Category:UncategorizedTag: :

I was implementing a custom writable stream in Node.js the other day when I ran into this issue where I wanted to know whether more data was coming or that we were actually done writing stuff. When looking at the recently revised API for stream implementers, the only thing that gets mentioned in the docs is the _write method.

After some intensive DuckDuckGoing (yes, this might become an actual word in the future), I ran into this thread on the Node.js user group and this issue on GitHub. In short, it is possible and even advisable to listen to the ‘finish’ event inside a Writable stream. Apparently, this happens all the time in the Node.js library itself. This means that by catching the ‘finish’ event, I was able to implement the flush functionality that I was looking for.

So without further ado, here’s a simple example of a custom Readable and Writable stream that are piped together. The Writable stream listen to the ‘finish’ event in order to flush stuff down the drain.

var stream = require('stream'),
    util = require('util');

//
// Reading stuff
//

var ReadingStuff = function() {
    this._data = [1, 2, 3, 4, 5];

    stream.Readable.call(this);
};

util.inherits(ReadingStuff, stream.Readable);

ReadingStuff.prototype._read = function() {
    if(0 === this._data.length) {
        this.push(null);
        return;
    }

    this.push(this._data[0].toString());
    this._data.shift();
};


//
// Writing stuff
//

var WritingStuff = function() {
    stream.Writable.call(this);

    this.on('finish', function() {
        console.log('Finished writing stuff!!');
    });
};

util.inherits(WritingStuff, stream.Writable);

WritingStuff.prototype._write = function(chunk, encoding, next) {
    console.log(chunk.toString(encoding));
    next();
};

//
// Application
//

var readingStuff = new ReadingStuff();
var writingStuff = new WritingStuff();

readingStuff.pipe(writingStuff);

 

Notice that inside the _read method of our custom Readable stream, we call this.push(null) in order signal the end of the data.

Hope this helps.