Mastering the Duplex Stream Pattern
In this lesson, you will learn how to create a single, unified interface that functions as both a data source and a data destination simultaneously.
The Two-Way Street
Up until now, you have worked with streams that either push data out (Readable) or consume data fed into them (Writable). However, many real-world tasks—like a network socket or a communication channel—require you to read and write data at the same time. This is where the Duplex Stream comes in.
A Duplex stream is an object that implements both the Readable and Writable interfaces. It is essentially an "encapsulated unit" where the two streams share the same internal state. When you pipe data into a Duplex stream, it processes the input and makes it available for others to read.
Thinking Like a Socket
Imagine you are building a logging proxy. You want to accept raw log entries (Writable) and emit formatted audit reports (Readable) in one go. Instead of managing two separate objects, you combine them:
const { Duplex } = require('stream');
const myDuplex = new Duplex({
write(chunk, encoding, callback) {
// Act as Writable: store the incoming data
this.buffer = chunk.toString();
callback();
},
read(size) {
// Act as Readable: push the processed data out
if (this.buffer) {
this.push(`Processed: ${this.buffer}`);
this.buffer = null;
} else {
this.push(null); // End the stream
}
}
});
In this pattern, the write side handles incoming data, while the read side allows downstream consumers to pull what has been processed. Because these reside in the same object, you can link them into a pipeline seamlessly. You aren't just passing data through; you are creating a "smart" pipeline component that owns its own input/output lifecycle. By encapsulating both roles, you keep your code clean and prevent the complexity of juggling separate stream instances for bidirectional communication.
Key Takeaway: A Duplex stream encapsulates bidirectional data flow by combining readable and writable interfaces into a single object, allowing you to handle input and output within one cohesive unit.