Skip to content

Instantly share code, notes, and snippets.

@tail-call
Created August 13, 2017 09:50
Show Gist options
  • Save tail-call/951dadbb25b3ada8c4610519576d8bd5 to your computer and use it in GitHub Desktop.
Save tail-call/951dadbb25b3ada8c4610519576d8bd5 to your computer and use it in GitHub Desktop.
Object stream example
// Number stream example
"use strict"
const stream = require("stream")
let numberStream = new class extends stream.Readable {
constructor () {
// This is an object stream
super({ objectMode: true })
this.counter = 0
}
_read () {
this.push(this.counter++)
}
}
let squareStringStream = new class extends stream.Transform {
constructor () {
// This is an object stream
super({ objectMode: true })
}
_transform (number, _, callback) {
this.push(`${number * number}\n`)
// Callback must be called to verify that write succeeded
callback()
}
_final () {
}
}
numberStream.pipe(squareStringStream)
squareStringStream.pipe(process.stdout)
// Exit process on EPIPE (stdout is closed, i.e. when piped to head(1)
// command)
process.stdout.on("error", (...stuff) => process.exit(0))
@tail-call
Copy link
Author

tail-call commented Aug 13, 2017

You could actually split squareStringStream into squareStream, which would square numbers, and lineStream, which would produce "\n"-postfixed strings from input objects, but that'd be boring, so I haven't done that.

Important parts are object mode flag, so the whole thing doesn't choke on trying to push something that isn't either Buffer or String:

super({ objectMode: true })

and EPIPE guardnote, which is pretty much only useful for command line programs:

process.stdout.on("error", (...stuff) => process.exit(0))

note famous epipe problem solved in recent Node releases is a different issue, and you still have to guard against EPIPE when manually redirecting streams to stdout

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment