2

I have a no-op Transform stream test that outputs the list of all files passed through it. Why does the following code outputs the list of files only once? How do I compose two streams properly?

var composed = test().pipe(test());
gulp.src('source/*').pipe(composed);

2 Answers 2

2

To compose streams, you pipe() the first to the second, but you also have to modify pipe() and unpipe() so they apply to the second stream. This way additional calls to pipe() on the composed stream will use the output of the second stream instead of the first.

function compose(s1, s2) {
    s1.pipe(s2);
    s1.pipe = function (dest) {
        return s2.pipe(dest);
    }
    s1.unpipe = function (dest) {
        return s2.unpipe(dest);
    }
    return s1;
}

var composed = compose(test(), test());
gulp.src('source/*')
    .pipe( composed )  // src -> s1 -> s2
    .pipe( ... );      // s2 -> ...
Sign up to request clarification or add additional context in comments.

3 Comments

That's what I eventually did. The problem is that result of such compose operation is inconsistent: it has pipe of second stream, but events and properties of first. The cleaner approach would be to create a new stream class from scratch, but there's a wide variety of stream types, and the resulting stream could be Readable, Writable of Transform depending on types of passed streams. I haven't found a way to check for stream types to make this possible.
Yes. You could also overwrite the returned s1's on() method to link to s2 for event, but that still doesn't give properties. The complete solution would be a to implement a full new stream.
As answered here: how-to-compose-transform-streams-in-node-js one can use the module multipipe to compose streams.
1

pipe() returns the stream being piped to, not from (to allow chaining). So the second line is basically trying to pipe to the second instance of test(). What you need to do instead is:

var first = test();
first.pipe(test());
gulp.src('source/*').pipe(first);

Or:

gulp.src('source/*')
    .pipe(test())
    .pipe(test());

2 Comments

Awesome. I don't have an idea why I couldn't figure this out myself.
(The second is not an option for me, as it isn't a composed stream. Though you should do it this way in most cases.)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.