1

Working with a POC using Bacon.js and run into a little bit of an issue with Property values.

I am able to retrieve all new property values in the onValue callback however I would like to know what the old property value was before this new value has been set. So far I have not found any easy or elegant solution to achieve this in Bacon out of the box...am I missing something.

Even Object.observe() has a way to get to the old value of the property so surprised I cannot find equivalent behaviour in Bacon.

Would anyone have any suggestions how to handle this? Obviously I do not want to persist the latest property value anywhere in the client code strcily for the sake of being able to do the comparisons between old and new...

Moonwalker
  • 3,462
  • 4
  • 25
  • 31

2 Answers2

1

You could use slidingwindow to create a new observable with the 2 latest values:

var myProperty = Bacon.sequentially(10, [1,2,3,4,5]) // replace with real property
var slidingWindow = myProperty.startWith(null).slidingWindow(2,2)
slidingWindow.onValues(function(oldValue, newValue) {
  // do something with the values
})
OlliM
  • 7,023
  • 1
  • 36
  • 47
  • Brilliant. This works great and much nicer than my cookie cutter approach. Thank you. – Moonwalker Sep 05 '15 at 10:14
  • Using the second argument to `slidingWindow`, you can also make it fire only when there are at least 2 values to compare. Even further, you may use `onValues` instead of `onValue` to cut some more boilerplate. – raimohanska Sep 07 '15 at 08:46
  • Thanks @raimohanska, using `startWith` and `onValues`, this got even simpler. – OlliM Sep 07 '15 at 11:25
  • Actually @OlliM, your initial approach is a more flexible solution. The modifications you made impose a strict requirement that both values have to be present before event is triggered which is not exactly appropriate in all cases, at least not in mine. I suggest you revise your answer and include both approaches.. – Moonwalker Sep 09 '15 at 10:37
  • Should not require both values, that's why I added the `.startWith(null)`, so that when the first real value comes out, slidingWindow has value `[null, realValue]`. – OlliM Sep 10 '15 at 11:39
0

Due to lack of the functionality in the native Bacon.js I implemented a custom solution with a wrapper object that holds on to the latest value after it had been forwarded to the subscriber. So instead of tapping into the lens directly client code works with the obsever which also has additional benefits of restricting write access to the model through the lens from client code which is what I needed as well.

    function Observer (lens) {
       this.lastValue = undefined;
       this.lens = lens;
    };

    Observer.prototype = {
        onValue(onValueCallback){
            this.subscription = this.lens.onValue(function(newValue) {
                onValueCallback(this.lastValue, newValue);
                this.lastValue = newValue;
            });
        },
    };

    var model = new Bacon.Model({ type : "A"});
    var observer = new Observer(model.lens());
    observer.onValue(function(oldValue,newValue) { ... });
Moonwalker
  • 3,462
  • 4
  • 25
  • 31