Streams help handle data piece by piece instead of all at once. This saves memory and lets programs work faster with big data.
Stream types (Readable, Writable, Transform, Duplex) in Node.js
Start learning this pattern below
Jump into concepts and practice - no test required
const { Readable, Writable, Transform, Duplex } = require('stream');These are classes you can use to create different stream types.
Each stream type has specific methods to implement for your data flow.
const readable = new Readable({
read(size) {
this.push('Hello');
this.push(null); // No more data
}
});const writable = new Writable({
write(chunk, encoding, callback) {
console.log(chunk.toString());
callback();
}
});const transform = new Transform({
transform(chunk, encoding, callback) {
this.push(chunk.toString().toUpperCase());
callback();
}
});const duplex = new Duplex({
read(size) {
this.push('Data from read side');
this.push(null);
},
write(chunk, encoding, callback) {
console.log('Received:', chunk.toString());
callback();
}
});This program creates three streams. The readable stream sends numbers 1, 2, and 3. The transform stream doubles each number. The writable stream prints the doubled numbers. The streams are connected so data flows from readable to transform to writable.
const { Readable, Writable, Transform } = require('stream');
// Readable stream sends numbers 1 to 3
const readable = new Readable({
read() {
if (!this.current) this.current = 1;
if (this.current <= 3) {
this.push(this.current.toString());
this.current++;
} else {
this.push(null); // End
}
}
});
// Transform stream doubles the number
const transform = new Transform({
transform(chunk, encoding, callback) {
const num = Number(chunk.toString());
this.push((num * 2).toString());
callback();
}
});
// Writable stream prints the result
const writable = new Writable({
write(chunk, encoding, callback) {
console.log('Output:', chunk.toString());
callback();
}
});
// Connect streams: readable -> transform -> writable
readable.pipe(transform).pipe(writable);Always call callback() in writable and transform streams to signal you finished processing.
Use this.push(null) in readable streams to mark the end of data.
Duplex streams combine readable and writable in one object for two-way data flow.
Readable streams provide data piece by piece.
Writable streams accept and process data.
Transform streams change data while passing it along.
Duplex streams can both read and write data.
Practice
Solution
Step 1: Understand stream roles
Readable streams are designed to emit data chunks for consumption.Step 2: Match stream type to description
Only readable streams provide data piece by piece without accepting input.Final Answer:
Readable stream -> Option BQuick Check:
Readable = provides data [OK]
- Confusing writable streams as data providers
- Thinking transform streams only read data
- Mixing duplex with readable-only behavior
Solution
Step 1: Identify writable stream creation
Writable streams require a write method to handle incoming data chunks.Step 2: Check options for correct syntax
const stream = new Writable({ write(chunk, encoding, callback) { callback(); } }); correctly creates a Writable stream with a write method and callback.Final Answer:
const stream = new Writable({ write(chunk, encoding, callback) { callback(); } }); -> Option DQuick Check:
Writable needs write() method [OK]
- Using Readable constructor for writable stream
- Omitting write method in Writable options
- Confusing Transform or Duplex constructors
const { Transform } = require('stream');
const upperCase = new Transform({
transform(chunk, encoding, callback) {
this.push(chunk.toString().toUpperCase());
callback();
}
});
upperCase.on('data', data => console.log(data.toString()));
upperCase.write('hello');
upperCase.end();Solution
Step 1: Understand Transform stream behavior
The transform method converts input chunk to uppercase and pushes it forward.Step 2: Analyze event and output
The 'data' event logs the transformed chunk, which is uppercase 'HELLO'.Final Answer:
HELLO -> Option AQuick Check:
Transform changes data to uppercase [OK]
- Expecting original lowercase output
- Forgetting to call callback() in transform
- Assuming no output without explicit read
const { Duplex } = require('stream');
const duplex = new Duplex({
read(size) {
this.push('data');
},
write(chunk, encoding, callback) {
console.log(chunk.toString());
callback();
}
});
duplex.on('data', data => console.log('Received:', data.toString()));
duplex.write('hello');
Solution
Step 1: Check read method behavior
The read method pushes 'data' but never signals end by pushing null.Step 2: Understand stream end signaling
Streams must push null to indicate no more data; missing here causes hanging.Final Answer:
The read method should push null to signal end of data -> Option CQuick Check:
read() must push null to end stream [OK]
- Not pushing null in read method
- Forgetting callback in write method
- Assuming Duplex can't read and write
Solution
Step 1: Understand Duplex stream roles
Duplex streams can read and write independently; read() pushes data, write() processes input.Step 2: Match behavior to implementation
Push numbers 1 to 3 in read(), write() logs squares, and push null after last number to end stream.Final Answer:
Push numbers 1 to 3 in read(), write() logs squares, and push null after 3 -> Option AQuick Check:
Duplex reads numbers, writes squares [OK]
- Confusing Transform with Duplex for this task
- Not pushing null to end read stream
- Thinking Writable streams can read data
