Streams are collections of data that might not be available all at once, enabling efficient consumption of large files and network payloads without exhausting memory.
Stream Types Overview
| Type | Direction | Description |
|---|---|---|
Readable |
Read only | Source from which data can be consumed |
Writable |
Write only | Destination to which data can be written |
Transform |
Read & Write | Transforms or modifies data as it passes through |
Duplex |
Read & Write | Both readable and writable with independent channels (e.g. TCP socket) |
Pipeline & Modern stream/promises
Modern Node.js provides pipeline to safely link streams with automatic error handling and resource cleanup:
const { pipeline } = require('stream/promises');
const fs = require('fs');
const zlib = require('zlib');
async function compressFile() {
await pipeline(
fs.createReadStream('source.tar'),
zlib.createGzip(),
fs.createWriteStream('source.tar.gz')
);
console.log('Compression complete');
}
Creating Custom Streams
1. Custom Readable Stream
const { Readable } = require('stream');
function createTimestampStream() {
let count = 0;
return new Readable({
objectMode: true,
read() {
if (count >= 5) {
this.push(null); // End of stream
} else {
this.push({ id: ++count, time: new Date() });
}
}
});
}
2. Custom Transform Stream
const { Transform } = require('stream');
const uppercaseTransformer = new Transform({
transform(chunk, encoding, callback) {
const transformed = chunk.toString().toUpperCase();
callback(null, transformed);
}
});
3. Custom Writable Stream
const { Writable } = require('stream');
const consoleWriter = new Writable({
objectMode: true,
write(chunk, encoding, callback) {
console.log('Writing chunk:', chunk);
callback();
}
});
Flowing vs Paused Mode
Readable streams operate in either paused or flowing mode:
const stream = fs.createReadStream('data.csv');
// Attaching a 'data' listener automatically activates flowing mode
stream.on('data', (chunk) => {
console.log(`Received ${chunk.length} bytes`);
});
// Explicit flow control
stream.pause(); // Temporarily suspend events
stream.resume(); // Resume streaming events
Stream Events
| Event | Applicable To | Trigger Condition |
|---|---|---|
data |
Readable | Emitted when a chunk of data is ready |
end |
Readable | Emitted when no more data is available |
finish |
Writable | Emitted when all written data has been flushed |
error |
All | Emitted whenever an unhandled stream error occurs |
close |
All | Emitted when the underlying descriptor is closed |