8

Like the title says. Is there a way to modify a observed valued without triggering the observer callback in Polymer?

For example

Polymer({
        is: 'my-component',

        properties: {
            aValue: {
                type: Number,
                value: 0,
                observer: '_valueChanged',
                notify: true
            },
            ref: {
                type: Object,
                computed: '_computeRef(channel, channelNumber)'
            }
        },

        _computeRef: function(channel, channelNumber) {

            var ref = new Firebase("/*link*/");
            ref.on("child_changed", function(data) {
               this.aValue.setWithoutCallingObserver(data.val());
            }.bind(this));

            return ref;
        },

        _valueChanged: function() {
            var message = { aValue: this.aValue };
            if (this.ref) {
                this.ref.set(message);
            }
        }

    });

This would be useful because now I am experiencing lag in the following scenario:

  1. Adapting aValue in a third party app
  2. Firebase updates all clients
  3. The .on callback sets the value and triggers the observer callback
  4. Causes a .set to firebase
  5. go back to 2.

Update: The issue is not firebase related. I believe the solution is in getting control over how updates are applied to observed values in Polymer. Partly because changes to the values in the firebase store can be made by 3th party (not necessarily web) applications too.

Jeremy Knees
  • 640
  • 1
  • 7
  • 18
  • possible duplicate of [Firebase syncing causes lag](http://stackoverflow.com/questions/32529499/firebase-syncing-causes-lag) – Frank van Puffelen Sep 19 '15 at 16:03
  • You can add a new variable firebaseValue and update it in your _computeRef function. In the _valueChanged function call ref.set only if aValue is different from firebaseValue. – Srik Sep 21 '15 at 00:01

2 Answers2

4

To my knowledge, there is not built in way to set a property value without triggering it's observer.

You don't have control over how/when/with what arguments the observer is called, but you do have control over the procedure body and, luckily, you are working with a shared state (this).

So, you can modify the behavior of the function based on a flag that can be accessed from within the function, but doesn't have to be passed in.

For example:

_valueChanged: function (new_val, old_val) {
   if (this._observerLock) { return; }

   var message = { aValue: this.aValue };
     if (this.ref) {
       this.ref.set(message);
     }
   }
 }, 
...

Then, you can implement the _setWithoutCallingObserver() method like:

_setWithoutCallingObserver: function (value) {
  this._observerLock = true;
  this.aValue = value;
  this._observerLock = false;
}
Luke
  • 5,047
  • 4
  • 31
  • 58
-1

Just change the _valueChangedMethod to this

_valueChanged: function(newValue, oldValue) {
        if(newValue == oldValue) return;
        var message = { aValue: this.aValue };
        if (this.ref) {
            this.ref.set(message);
        }
    }

This will make the observer do its work only if the value actually changed.

Alan Dávalos
  • 2,119
  • 10
  • 18