Search code examples
javascriptbacon.js

Bacon.js EventStream from value


Let's say I have an arbitrary value in my code: var arbitraryValue = null;

There are multiple places in my code that can change this value. Can I create an EventStream which is based on the changes of the this value? In other words, if arbitraryValue is changed, the new value is sent to the subscribers as an EventStream?


Solution

  • Thanks for your answers! Perhaps Bacon.js was not what I was looking for so I decided to make my own "Reactive Programming" library. It calculates new values immediately without the need to check the value with setTimeout.

    var = createReactiveValue = function(initialValue) {
    return {
        "observers": [], // Call these functions with a new value when it has been set
        "value":initialValue,
        "set": function(newValue) {
            this.value = newValue;
    
            this.observers.forEach(function(observer) {
                // Call observers asynchronously
                setTimeout(function() { observer(this.value) }, 0);
            })
        },
        "get": function() {
            return this.value;
        },
        "addObserver": function(observer) {
            this.observers.push(observer);
        }
    };
    };
    
    // If any of the dependant values change, sets reactive value 'value' to the result of calling 'result'
    var = makeReaction = function(value, dependencies, result) {
        // Start watching changes in dependencies
        dependencies.forEach(function(dependency) {
            dependency.addObserver(function(newValue) {
                var newResult = result(value, dependencies);
                value.set(newResult);
            });
        });
    };
    
    
    // When 'reactiveValue' is changed, calls the given 'result' function with the new value
    var = watchReaction = function(reactiveValue, result) {
        // Start watching changes in reactive value
        reactiveValue.addObserver(function(newValue) {
            result(newValue);
        });
    };
    
    var a = createReactiveValue(2);
    var b = createReactiveValue(1);
    var c = createReactiveValue(null);
    
    // We want c to depend on both a and b. If either a or b change, c should    automatically recalculate it's value
    makeReaction(c, [a, b], function(c, [a, b]) {
        return a.get() + b.get();
    });
    
    // If c is changed, for whatever reason, log it
    watchReaction(c, function(newC) {
        console.log("Reaction completed: " + a.get() + " + " + b.get() + " = " + c.get());
    });
    
    // Test it by resetting value a to random
    setInterval(function()
    {
        var newValue = Math.random();
        a.set(newValue); },
    1000); // Logs the new result imm
    

    EDIT: Now available as a library: https://github.com/Jarzka/ReaktioJS