In this lesson, you will learn how to create a Transform stream to modify data in real-time as it travels from a source to a destination.
Moving Data Through a Filter
Up until now, we have moved data from a Readable source to a Writable sink using pipes. However, raw data is rarely perfect. Often, you need to sanitize, compress, encrypt, or convert data format on the fly. A Transform stream acts as an intelligent intermediary: it consumes data, modifies it, and pushes the result downstream without needing to load the entire dataset into memory.
Think of it like a factory conveyor belt: raw materials (data chunks) enter the machine, the machine applies a specific process, and the refined product exits the other side.
Implementing a Custom Transform Stream
To create your own transformation logic, you extend the Transform class from the stream module and implement the _transform method.
const { Transform } = require('stream');
const upperCaseTransformer = new Transform({
transform(chunk, encoding, callback) {
// 1. Modify the data
const transformed = chunk.toString().toUpperCase();
// 2. Push the result downstream
this.push(transformed);
// 3. Signal that we are ready for the next chunk
callback();
}
});
When the stream receives a chunk, it performs the transformation and calls callback(). This callback is crucial; it acts as the flow control mechanism that respects backpressure. By waiting to call callback() until the transformation is complete, the stream ensures it doesn't get overwhelmed if the downstream consumer is moving slower than the producer.
Why not just process it at the end?
You might be tempted to wait until all data is received to process it. However, if you are handling a 5GB file, that approach would crash your process by exceeding your heap memory limits. By using a Transform stream, you process one small chunk at a time, keeping your memory footprint constant regardless of the total file size.
Key Takeaway: A Transform stream allows you to process data in small, manageable chunks, keeping memory usage low while dynamically altering the stream’s content.