Now that we know how to use events, we can dig into one of my favorite parts of the node.js core: readable & writeable streams.
First, we'll walk through some examples of piping in Unix-like environments, since it would be good to know what node.js streams are emulating.
Unix Pipeline
Let's look at the contexts of an example text file by using the cat command to output the contents of the file to stdout.
$ cat names.txt Gordon Mike Brennen Casey Toni Pamela Nick Joe Randy Ben Jenny Tyler Pete Chris Rob Dave Jeff Erik Paul
Now, let's assume we want to reduce the list of names to names with less than four characters. We can pipe the output of cat to sed (with a simple regex) to accomplish this.
$ cat names.txt | sed '/.\{4\}/d' Joe Ben Rob
Now that we have filtered the list to get the names we were looking for, let's sort the names in reverse dictonary order by piping the output of sed to sort.
$ cat names.txt | sed '/.\{4\}/d' | sort --dictionary-order --reverse Rob Joe Ben
Pretty neat, huh? By piping the output of one simple program to the input of another simple program, you can accomplish complex tasks easily & quickly without having to have one behemoth program that reads files, filters, sorts, etc. If you'd like to learn more specifically about piping in Unix environments, check out the standard IO section of Brennen Bearnes' userland book.
Node.js Streams
Now that you have an idea what inspired the stream API, let's try something similar using the node.js stream pipe() command.
Let's say we want to view the state of the button from our SSH connection. Since stdout is a writable stream, we can pipe the output of the button directly to stdout. Let's assume we have a tactile button attached to pin 17 on our Raspberry Pi.
First, install the gpio-stream
package with npm
:
$ npm install gpio-stream
Next, save the following code in a file called stdout.js
:
var GpioStream = require('gpio-stream'), button = GpioStream.readable(17); // pipe the button presses to stdout button.pipe(process.stdout);
That was pretty simple. What if we wanted to redirect the output of our button to light up a LED on pin 18?
var GpioStream = require('gpio-stream'), button = GpioStream.readable(17), led = GpioStream.writable(18); // pipe the button presses to the LED button.pipe(led);
Chunked Transfer Stream
Now that you have a couple simple examples under your belt, let's try something a bit more interesting. What if we wanted to output our button presses to the LED & a web browser? Since the node.js HTTP server response is a writable stream, we can pipe the button presses to the LED, and then to the HTTP response object. Your browser can receive the presses on the fly using chunked transfer encoding. All of that with ~10 lines of code!
var GpioStream = require('gpio-stream'), http = require('http'), button = GpioStream.readable(17), led = GpioStream.writable(18); var stream = button.pipe(led); http.createServer(function (req, res) { res.setHeader('Content-Type', 'text/html'); res.write('<pre>logging button presses:\n'); stream.pipe(res); }).listen(8080);
You could pipe the button presses to a file, a web service, or pretty much anything you can think of thanks to the endless number of stream packages available in npm. The button example is a simple one, but this same concept can be applied to a wide range of sensors.
Speaking of npm, let's examine how to use npm to manage third party packages. We'll even look at how you can create your own npm package and publish it for everyone to use!
Text editor powered by tinymce.