1

Let's say I have two bacon.js streams:

const stream1 = $('#input1').asEventStream('input')
    .map(e => e.target.value)
    .filter(inp => inp.length > 3)
    .log();
const stream2 = $('#input2').asEventStream('input')
    .map(e => e.target.value)
    .filter(inp => inp.length > 3)
    .log();

I would like to extract the common step of filtering of by the input length into a variable and apply it to both of the streams afterwards, fantasy code:

const my_filter = Bacon.map(e => e.target.value).filter(inp => inp.length > 3)
const stream1 = $('#input1').asEventStream('input')
    .apply(my_filter)
    .log();
const stream2 = $('#input2').asEventStream('input')
    .apply(my_filter)
    .log();

Is there an idiomatic way to do that?

EDIT1: To clarify, my_filter is just an example. I would like to be able to refactor an arbitrary chain of combinators and apply them to multiple streams.

EDIT2: As Bless Yahu noticed, I need an additional map to get the value out of events. This demonstrates my problem even better.

Dimitri Vorona
  • 450
  • 3
  • 13

2 Answers2

1

To me this looks like a basic software refactoring problem.

Generally, if you want to apply an arbitrary transformation to a stream, you'll probably want to write a function that takes a stream as an argument and returns the modified stream as a result.

In your particular case I'd remove duplication by extracting steps into functions.

const getValue = input => input.target.value
const my_filter = stream => stream.filter(text => text.length > 3)
const filteredInputValue = ($input) => {
  my_filter($input.asEventStream('input').map(getValue))
const stream1 = filteredInputValue($('#input1')).log()
const stream2 = filteredInputValue($('#input2')).log()

In this example, you can easily modify my_filter to apply any other transformations as well, like throttling and text trimming.

raimohanska
  • 3,265
  • 17
  • 28
0

Add a mapping function to get the value out of the event (I think there is a Bacon convience function as well), change you my_filter to a function, and call it with filter in your stream:

const getValue = inp=>inp.target.value;
const my_filter = inp => inp.length > 3
const stream1 = $('#input1').asEventStream('input')
    .map(getValue)
    .filter(my_filter)
    .log();
const stream2 = $('#input2').asEventStream('input')
    .map(getValue)
    .filter(my_filter)
    .log();

example of this is here: http://jsbin.com/vahejuv/edit?html,js,console,output

Bless Yahu
  • 1,331
  • 1
  • 12
  • 25