Frage

Is there an easier way to implement combine3?

var Bacon = require('baconjs')

function emit(delay)
{
        var s = new Bacon.Bus()
        setTimeout(function ()
        {
                console.log("emit", delay)
                s.push(delay)
        }, delay)
        return s.toProperty()
}

var foo = emit(500)
var bar = emit(1000)
var baz = emit(1500)

function consume(foo, bar, baz)
{
        console.log("consumed", foo, bar, baz)
}

function combine3(consume, foo, bar, quux)
{
        Bacon.combineWith(function (foo, bar, quux)
        {
                return { foo : foo, bar : bar, quux : quux }
        }, foo, bar, quux)
        .onValue(function (x)
        {
                consume(x.foo, x.bar, x.quux)
        })
}

combine3(consume, foo, bar, baz)

Note that combineWith alone doesn't work unless a dummy onValue() consumer is present:

Bacon.combineWith(consume, foo, bar, baz).onValue(function () {})

The workaround still looks like a hack. The following 3 versions don't call consume():

Bacon.when([foo, bar, baz], consume)
Bacon.update(911, [foo, bar, baz], consume)
Bacon.zipWith(foo, bar, baz, consume)

The task at hand is to filter an HTML table based on 3 parameters. so consume draws a table based on currently selected filtering conditions and doesn't produce new Observables.

Also, is there a simpler way to write emit()?

War es hilfreich?

Lösung

Then combineWith method is used to create a new Property from existing Observables (Properties and EventStreams). All Observables are lazy, i.e. do not register to underlying sources unless they have at least one Subscriber.

You should not confuse composition of Observables (with combine, zip, when, update etc) to assigning side-effects, i.e. registering Subscribers. If you want your "consume" function to be called on values in an Observable, you need to register it as a Subscriber.

Still, there's the issue that Bacon events only carry one value, so you cannot use N-ary functions with onValue. You can, though, make your Observable contain arrays as values and the use the "onValues" method that splits the value array as arguments to an N-ary function.

So, one way to do this is

// Property that emits values as arrays of [foo, bar, baz]
var combined = Bacon.combineAsArray(foo, bar, baz)
// Assign side effect. Split value arrays to 3-ary function.
combined.onValues(consume)

Because I found it to be quite a common case that you want to combine N Observables and apply an N-ary function on values, there's a shorthand method "Bacon.onValues" for this. So, the simplest answer would be just

Bacon.onValues(foo, bar, baz, consume)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top