node.jsstreamchunksmultiplexing

Simple multiplexing node.js stream - chunk concatenated issue


Im trying to implement a simple node.js stream multiplexer/demultiplexer.

Currently while implementing the multiplexing mechanism i noticed that the output of the multiplexer gets concatenated into a single chunk.

const { PassThrough, Transform } = require("stream");

class Mux extends PassThrough {

    constructor(options) {
        super(options);
    }

    input(id, options) {

        let encode = new Transform({
            transform(chunk, encoding, cb) {

                let buf = Buffer.alloc(chunk.length + 1);
                buf.writeUInt8(id, 0);

                chunk.copy(buf, 1);

                cb(null, buf);

            },
            ...options
        });

        encode.pipe(this);

        return encode;

    };

};

const mux = new Mux();

mux.on("readable", () => {
    console.log("mux >", mux.read())
});

const in1 = mux.input(1);
const in2 = mux.input(2);


in1.write(Buffer.alloc(3).fill(255));
in2.write(Buffer.alloc(3).fill(127));

Output looks like this: mux > <Buffer 01 ff ff ff 02 7f 7f 7f>. I would have thought that i receive two console.log outputs.

Expected output:

mux > <Buffer 01 ff ff ff>

mux > <Buffer 02 7f 7f 7f>

Can some one explains why i only get one "readable" event and a concatenated chunk from both inputs?


Solution

  • Use the data event and read from the callback:

    The 'data' event is emitted whenever the stream is relinquishing ownership of a chunk of data to a consumer.

    mux.on("data", d => {
        console.log("mux >", d)
    });
    

    This now yields:

    mux > <Buffer 01 ff ff ff>
    mux > <Buffer 02 7f 7f 7f>
    

    Why readable is only emitted once is explained in the docs as well:

    The 'readable' event will also be emitted once the end of the stream data has been reached but before the 'end' event is emitted.

    data and readable behave differently. In your case readable is never emitted until the end of the stream data has been reached, which returns all the data at once. data is emitted on each available chunk.