A stream in Node is simply a sequence of bytes. A stream contains a buffer of bytes, and this buffer has a zero or greater length. In Node, streams are objects representing data flows that can be written to and read from asynchronously. The Stream interface is an abstract interface. An abstract interface function is like a blueprint which tells the user what kinds of data types or functions need to be implemented while creating an instance of Stream. Example, a Readable stream implementation is required to implement a public read method which delegates to the interface’s internal _read method.
In general, all stream implementations should follow these guidelines: 1. As long as data exists to send, write to a stream until that operation returns false, at which point the implementation should wait for a drain event, indicating that the buffered stream data has emptied. 2. Continue to call read until a null value is received, at which point wait for a readable event prior to resuming reads. 3. Several Node I/O modules are implemented as streams. Network sockets, file readers and writers, stdin and stdout, zlib, and so on. Similarly, when implementing a readable data source, or data reader, one should implement that interface as a Stream interface.
Readable Stream: Streams producing data that another process may have an interest in are implemented using a Readable stream. A Readable stream saves the implementer the work of managing the read queue, handling the emitting of data events, etc. Readable base class takes 3 attributes: i) encoding: Decode buffers into the specified encoding, defaulting to UTF-8. ii) highWaterMark: Number of bytes to keep in the internal buffer before ceasing to read from the data source. The default is 16 KB. iii) objectMode: Tell the stream to behave as a stream of objects instead of a stream of bytes, such as a stream of JSON objects instead of the bytes in a file. Default false.
var Feed = function(channel)
{
var readable = new stream.Readable(
{
encoding : "utf8"
});
var news = ["Big Win!", "Stocks Down!","Actor Sad!"];
readable._read = function()
{
if(news.length)
{
return readable.push(news.shift() + "\n");
}
readable.push(null);
};
return readable;
}
Writable Stream: A Writable stream is responsible for accepting some value and writing that data to a destination. Writable base class takes attributes: i) highWaterMark: The maximum number of bytes the stream’s buffer will accept prior to returning false on writes. Default is 16 KB. ii) decodeStrings: Whether to convert strings into buffers before writing. Default is true. Example, here we write 100 bytes to stdout:
var stream = require('stream');
var writable = new stream.Writable(
{
decodeStrings: false
});
writable._write = function(chunk, encoding, callback)
{
console.log(chunk);
callback();
}
var w = writable.write(Buffer.alloc(100));
writable.end();
console.log(w); // Will be `true`
Duplex Stream: A duplex stream is both readable and writeable. For instance, a TCP server created in Node exposes a socket that can be both read from and written to:
var stream = require("stream");
var net = require("net");
net
.createServer(
function(socket)
{
socket.write("Go ahead and type something!");
socket.on("readable", function()
{
process.stdout.write(this.read() || "")
});
}).listen(8080);
When the above code is executed, this code will create a TCP server that can be connected via Telnet: telnet 127.0.0.1 8080. Upon connection, the connecting terminal will print out ‘Go ahead and type something!’—writing to the socket. Any text entered in the connecting terminal will be echoed to the stdout of the terminal running the TCP server.