Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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);    
like image 205
axzr Avatar asked Oct 25 '25 06:10

axzr


2 Answers

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);        
    }
  }
}
like image 82
axzr Avatar answered Oct 26 '25 19:10

axzr


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.

like image 31
Michael Lehenbauer Avatar answered Oct 26 '25 20:10

Michael Lehenbauer



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!