Search code examples
node.jshapi.jsnode-streams

node.js conditional stream pipe


I'm trying to understand how best to conditionally pipe a stream to a Transform or similar without the use of a 3rd party lib.

Ideally I'd like to do something like this

const transformA, transformB = // my transforms
const booleanA, booleanB = // my various conditions

const stream = new Readable()
stream.push('...') // my content

return stream
         .pipe(booleanA && transformA)
         .pipe(booleanB && transformB)

I've attempted this using libs like detour-stream, ternary-stream and others but I've encountered various strange side effects where transforms are being invoked when they shouldn't, throwing errors etc, and its left me wondering about how people accomplish this type of thing without the added complexity of those libs.

In the interim I've solved this by just taking an imperative approach, reassigning the stream on each condition.

let stream = // get my stream

if (condition) stream = stream.pipe(someTransform)
if (otherCondition) stream = stream.pipe(otherTransform)

return stream

This is fine, but I'm still curious if the immutable and functional approach can be done

Thanks for looking & reading


Solution

  • Unfortunately, there's no built-in support for conditional pipes, an alternative to your approach without any third-party modules is using .pipeline

    const stream = require('stream');
    const pipeline = util.promisify(stream.pipeline);
    
    const read = new stream.Readable()
    
    const pipes = [
      booleanA && transformA,
      booleanB && transformB
    ].filter(Boolean); // remove empty pipes
    
    await pipeline(
       read,
       ...pipes
    );
    
    

    Since .pipeline takes N transform streams, you can make use of spread operator from an already filtered array of pipes.

    In case you want to return the last piped stream, you can drop the promisify version of pipeline.

    return pipeline(
       read,
       ...pipes,
       () => {}
    )