Streams & Buffers
Buffers
JavaScript (in the browser) has historically been poor at handling binary data. Node.js introduced theBuffer class to handle binary data efficiently.
A Buffer is a chunk of memory that stores raw binary data. It is similar to an array of integers but corresponds to a raw memory allocation outside the V8 heap.
Creating a Buffer
Streams
Streams are objects that let you read data from a source or write data to a destination in continuous chunks. There are four types of streams:- Readable: Stream you can read from (e.g.,
fs.createReadStream). - Writable: Stream you can write to (e.g.,
fs.createWriteStream). - Duplex: Stream that is both Readable and Writable (e.g.,
net.Socket). - Transform: Stream that can modify or transform the data as it is written and read (e.g.,
zlib.createGzip).
Why Streams?
If you want to read a massive file (e.g., 2GB video) and send it to a client:- Without Streams: You read the entire 2GB into memory. If 100 users do this, your server crashes.
- With Streams: You read small chunks (e.g., 64KB) and send them one by one. Memory usage remains low.
Readable Stream Example
Piping
Piping is a mechanism where we provide the output of one stream as the input to another stream. It is mainly used to get data from one stream and pass it to another.Stream Events
Streams are EventEmitters with specific events:Readable Stream Events
Writable Stream Events
Backpressure Handling
Backpressure occurs when data comes in faster than it can be written:Creating Custom Streams
Custom Readable Stream
Custom Writable Stream
Custom Transform Stream
Practical Example: HTTP File Download
Practical Example: Real-time Log Parser
pipeline() - Better Error Handling
Thepipeline() function handles errors and cleanup automatically:
Summary
- Buffers handle raw binary data efficiently
- Streams process data in chunks, enabling memory-efficient operations
- Four stream types: Readable, Writable, Duplex, Transform
- Piping connects streams and handles backpressure
- Backpressure prevents memory overflow when producer is faster than consumer
- Use
pipeline()for proper error handling and cleanup - Create custom streams by extending stream classes