Search code examples
javascriptproxy-classesfirebase

Generic Javascript proxy for Firebase


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);    

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);        
        }
      }
    }