Transform streams with Node's core stream module

Let's create a folder called core-transform-streams, initialize it as a package, install the readable-stream module, and create prototypal.js, classical.js, and modern.js files:

$ mkdir core-transform-streams 
$ cd core-transform-streams
$ npm init -y
$ npm install readable-stream
$ touch prototypal.js classical.js modern.js

We'll use these files to explore the evolution of stream creation.

Mostly when we use a core module, we use it directly. For instance, to work with streams we would do require('stream').

However, the rule of thumb is: never use the core stream module directly. While the name is a complete misnomer, we recommend always using the readable-stream module instead of the packaged core stream module; this will ensure any streams we create will be consistent across Node versions. So instead of require('stream'), we'll be using require('readable-stream'), which is the exact same thing, only with the behavior of most recent Node versions.

Let's write the following in prototypal.js:

const stream = require('readable-stream') 
const util = require('util')

function MyTransform(opts) {
stream.Transform.call(this, opts)
}

util.inherits(MyTransform, stream.Transform)

MyTransform.prototype._transform = function (chunk, enc, cb) {
cb(null, chunk.toString().toUpperCase())
}

const upper = new MyTransform()

process.stdin.pipe(upper).pipe(process.stdout)

In earlier versions of Node, this was the canonical way to create streams; with the advent of ECMAScript 2015 (ES6) classes, there's a slightly less noisy approach.

Let's make the classical.js file look as follows:

const { Transform } = require('readable-stream') 

class MyTransform extends Transform {
_transform (chunk, enc, cb) {
cb(null, chunk.toString().toUpperCase())
}
}

const upper = new MyTransform()

process.stdin.pipe(upper).pipe(process.stdout)

Still applying the abstract method paradigm with an underscored namespace is esoteric for JavaScript, and the use of classes is generally discouraged by the authors since, to be clear, ES6 classes are not classes - which leads to confusion.

In Node 4, support for the transform option was added; this allows for a more functional approach (similar to through2). Let's make modern.js look as follows:

const { Transform } = require('readable-stream') 

const upper = Transform({
transform: (chunk, enc, cb) => {
cb(null, chunk.toString().toUpperCase())
}
})

process.stdin.pipe(upper).pipe(process.stdout)

The Transform constructor doesn't require new invocation, so we can call it as a function. We can pass our transform function as the transform property on the options object passed to the Transform function.

This of course limits us to using Node 4 or above, so it isn't a recommended pattern for public modules; the prototypal approach is still most appropriate for modules we intend to publish to npm.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.218.5.12