Question

I'm using a proxy class as the data I have is a reference to a Firebase location that stores my object but I want to act as if I have the object itself. I've got something that works fine but I would like to improve it, the key criteria being to reduce repetition. I suspect something is possible by inspecting the Map class and using apply() but I don't know quite how to do that (or if there is a better solution).

I think it would also be useful if the solution could be generalised to support any class, not just the Map class.

var Map = function() {
  ...
};

var MapProxy = function(mapRef) {
  this.mapRef = mapRef;
};

Map.prototype.addToken = function(portrait, newLocation) {
  ...
};

Map.prototype.removeToken = function(token) {
  ...
};

Map.prototype.moveToken = function(token, newLocation) {
  ...
};

MapProxy.prototype.addToken = function(portrait, newLocation) {
  var mapRef = this.mapRef;

  mapRef.once('value', function(data) {
    var map = new Map();
    map.init(mapRef, data.val());

    map.addToken(portrait, newLocation);
  });
};

MapProxy.prototype.removeToken = function(token) {
  var mapRef = this.mapRef;

  mapRef.once('value', function(data) {
    var map = new Map();
    map.init(mapRef, data.val());

    map.removeToken(token);
  });
};

MapProxy.prototype.moveToken = function(token, newLocation) {
  var mapRef = this.mapRef;

  mapRef.once('value', function(data) {
    var map = new Map();
    map.init(mapRef, data.val());

    map.moveToken(token, newLocation);
  });
};

var mapProxy = new MapProxy(mapRef);    
Was it helpful?

Solution

Think I solved it myself in the end.

var FirebaseProxy = function(classToProxy, firebaseRef) {
  var key,
      self = this;

  self.proxy = classToProxy;
  self.firebaseRef = firebaseRef;

  for (key in self.proxy.prototype) {
    if (typeof self.proxy.prototype[key] === 'function') {
      (function(inner_key) {
        self[inner_key] = function ()
        {
          var args = arguments;

          self.firebaseRef.once('value', function(data) {
            var proxiedInstance = new self.proxy();

            if (typeof proxiedInstance.init === 'function') {
              proxiedInstance.init(self.firebaseRef, data.val());
            }

            proxiedInstance[inner_key].apply(proxiedInstance, args);
          });
        } 
      })(key);        
    }
  }
}

OTHER TIPS

I don't think I completely follow what you're trying to accomplish. Could you forego the proxy and just use something like this?

var Map = function(mapRef) {
  mapRef.on('value', function(snap) {
    this.init(snap.val());
  });
};

Map.prototype.init = function(data) {
  // update internal state with new data from Firebase ...
};

...

Since 'value' will fire every time the data at mapRef changes, your map object will always have the latest data.

It's worth noting that if you're going to be needing the latest map data on a regular basis, you should probably use .on(), not .once(). .once() will go and retrieve the data from the servers every time you ask for it, while .on() will always have the latest data cached (since it subscribes to updates). So it'll be faster and use less bandwidth.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top