Node.js Streams & Buffers 2 — Questions and Answers
Question 1: Which stream base class should you extend to implement a custom stream that both reads input and produces transformed output?
- stream.Readable
- stream.Transform (Correct answer)
- stream.Duplex
- stream.PassThrough
Correct answer: stream.Transform
stream.Transform is a Duplex subclass where the output is computed from the input, making it ideal for data conversion tasks like compression or encryption.
Question 2: What is the purpose of the highWaterMark option when creating a Node.js stream?
- Sets the maximum file size that can be streamed
- Defines the internal buffer size threshold before backpressure is applied (Correct answer)
- Limits the number of concurrent stream instances
- Sets the read timeout duration for the stream
Correct answer: Defines the internal buffer size threshold before backpressure is applied
highWaterMark specifies the number of bytes (or objects in object mode) that can accumulate in the internal buffer before backpressure is triggered.
Question 3: Which internal method must you implement when subclassing stream.Readable to provide data to consumers?
- _write()
- _transform()
- _read() (Correct answer)
- _flush()
Correct answer: _read()
The _read() method is called by the stream internals when a consumer requests more data; you call this.push() inside it to supply chunks.
Question 4: Why is stream.pipeline() preferred over readable.pipe() for production code?
- It provides better throughput on large files
- It handles errors and automatically destroys all streams in the pipeline (Correct answer)
- It supports older Node.js versions that lack pipe()
- It enables bidirectional data flow between streams
Correct answer: It handles errors and automatically destroys all streams in the pipeline
stream.pipeline() propagates errors to a callback and destroys all piped streams on failure, preventing resource leaks that pipe() alone does not handle.
Question 5: How do you create a Buffer from a hexadecimal string in Node.js?
- Buffer.from('deadbeef')
- Buffer.from('deadbeef', 'hex') (Correct answer)
- Buffer.fromHex('deadbeef')
- new Buffer('deadbeef', 16)
Correct answer: Buffer.from('deadbeef', 'hex')
Buffer.from() accepts an encoding as the second argument; passing 'hex' interprets each pair of characters as a byte value.
Question 6: What does calling readable.push(null) inside a custom Readable stream signify?
- Clears the stream's internal buffer
- Temporarily pauses the stream
- Signals the end of the stream (EOF) (Correct answer)
- Resets the stream to its initial state
Correct answer: Signals the end of the stream (EOF)
Pushing null is the sentinel value that tells Node.js the Readable stream has no more data to provide, triggering the 'end' event for consumers.
Question 7: In Node.js object mode streams, what type of data can be passed as a chunk?
- Fixed-size byte chunks only
- UTF-8 encoded strings only
- Any JavaScript value including objects, arrays, and primitives (Correct answer)
- Only JSON-serializable data structures
Correct answer: Any JavaScript value including objects, arrays, and primitives
Object mode removes the Buffer/string restriction, allowing streams to work with arbitrary JavaScript values such as parsed objects or database rows.
Which stream base class should you extend to implement a custom stream that both reads input and produces transformed output?