0

I go for data-binding using ECMA7 Object.observe or Mozilla Object.watch instead of eventEmitter of node.

For Object.observe, I cannnot find any implementation around for android browser compatiblity. They basically must use setTimeout polling, so I gave up.

Instead, Object.watch can run without any polling with a library for Chrome, and natively Firefox etc.

The code I found is

if (!Object.prototype.watch)
{
    Object.defineProperty(Object.prototype, "watch",
    {
        enumerable: false,
        configurable: true,
        writable: false,
        value: function(prop, handler)
        {
            var
            oldval = this[prop],
                newval = oldval,
                getter = function()
                {
                    return newval;
                },
                setter = function(val)
                {
                    oldval = newval;
                    return newval = handler.call(this, prop, oldval, val);
                };

            if (delete this[prop])
            { // can't watch constants
                Object.defineProperty(this, prop,
                {
                    get: getter,
                    set: setter,
                    enumerable: true,
                    configurable: true
                });
            }
        }
    });
}

// object.unwatch
if (!Object.prototype.unwatch)
{
    Object.defineProperty(Object.prototype, "unwatch",
    {
        enumerable: false,
        configurable: true,
        writable: false,
        value: function(prop)
        {
            var val = this[prop];
            delete this[prop]; // remove accessors
            this[prop] = val;
        }
    });
}

This works with

obj.watch('foo',
      function(id, oldval, newval)
      {
        //..........

        return newval;
      });

However, a big problem occurs, which is, when I implement multiple watch in various places, the only first obj.watch is triggered, and never for the rest.

The reason is obvious.

On the first trigger, the rest obj.watch is automatically set to watch the changed value.

Test code:

var obj = {
      foo: 5
    };

obj.watch('foo',
  function(id, oldval, newval)
  {
    alert(newval);

    return newval;
  });

obj.watch('foo',
  function(id, oldval, newval)
  {
    alert(newval);

    return newval;
  });

obj.foo = 7;

Result: no error, but alerted only once.

Actually, I try to find alternative library/mechanism that allow to trigger multiple watch-blocks for the same object instance/property.

Again, I will avoid eventEmitter pattern but observer pattern. Do you have any idea? Thanks.

Bergi
  • 513,640
  • 108
  • 821
  • 1,164

3 Answers3

0

Self Answer.

not sure yet, but one way is to use
melanke/Watch.JS/ https://github.com/melanke/Watch.JS/ that I have known this for a long time.

It does job:

http://jsfiddle.net/NbJuh/62/

//defining our object no matter which way we want
var obj = {
    foo: "initial value of attr1" 
};

//defining a 'watcher' for an attribute
watch(obj, "foo", function(){
    alert("foo changes!");
});
watch(obj, "foo", function(){
    alert("foo changes!");
});
//when changing the attribute its watcher will be invoked
obj.foo = "other value";
0

Here is small lib very close to what you looking for

https://github.com/imolus/js-object-watch

Oleg Imanilov
  • 2,268
  • 1
  • 11
  • 21
0

A well made Object.defineProperty should do the trick.

A more modern approach would be to use a Proxy with new Proxy(object, {...}).

Walle Cyril
  • 2,691
  • 2
  • 16
  • 46