从GeoQuery获取$ firebaseArray

时间:2015-04-17 20:24:53

标签: firebase angularfire

我将firebase与GeoFire,AngularFire和常规JavaScript API结合使用。

在我的应用程序中,GeoQuery通过订阅.on("key_entered")事件返回对象键列表。然后我可以使用.once()查询方法获取对象。但是,我真正需要做的是有一个synchronized数组,其中包含GeoQuery返回键的对象。我还需要通过createdAt时间戳来限制/订购这些时间戳,以免下载每个对象。当新对象点击我的.on("key_entered")事件时,应将它们添加到数组中。

经过大量的研究,我无法弄清楚如何做到这一点。可能吗?如果没有,那么对我来说这是解决这个问题的最佳途径。

2 个答案:

答案 0 :(得分:1)

是的,这是可能的。

您必须在$firebaseArray事件(key_使用$firebaseArray事件)之上构建类似于child_逻辑的类。

因为AngularFire项目在Github上可用,所以这是一个很好的起点:https://github.com/firebase/angularfire/blob/master/src/FirebaseArray.js

答案 1 :(得分:0)

一种可能的解决方案,但未经过测试:

/*global angular,Firebase,GeoFire,_*/
(function() {
  'use strict';

  angular.module('app').provider('GeofireService', function GeofireServiceProvider() {
    var firebaseRef = "";

    this.setUrl = function(firebaseUrl) {
      firebaseRef = firebaseUrl;
    };

    this.$get = [
      '$rootScope',
      '$firebaseUtils',
      function($rootScope, $firebaseUtils) {

        function GeofireService() {
          var self = this;
          this._firebase = new Firebase(firebaseRef);
          this._itemsRef = this._firebase.child('items');
          this._geoRef = this._firebase.child('_geofire');
          this._geofire = new GeoFire(this._geoRef);
          this._list = [];
          this._observers = [];
          this._sync = new QueryArraySync(this);

          $firebaseUtils.getPublicMethods(self, function(fn, key) {
            self._list[key] = fn.bind(self);
          });

          this._sync.init(this._list);

          return this._list;
        }

        GeofireService.prototype = {
          add: function(item) {
            var itemID = this._itemsRef.push(item);
            var thatItem = item;
            thatItem.id = itemID.key();
            var geofirePromise = this._geofire.set(
              thatItem.id, [thatItem.coord.latitude, thatItem.coord.longitude]);
            return geofirePromise.then(function() {
              return thatItem;
            });
          },
          //Update does not update geofire location, only the item
          update: function(id, item) {
            var defer = $firebaseUtils.defer();
            var itemRef = this._itemsRef.child(id);
            //TODO test if undefined or item does not exist
            itemRef.update(item, function(err) {
              if (err) {
                //TODO noooooooooooo
                defer.reject(err);
              }
              defer.resolve(id);
            });
            return defer.promise;
          },
          getById: function(id) {
            var defer = $firebaseUtils.defer();
            var itemRef = this._itemsRef.child(id);
            itemRef.on('value', function(snap) {
              defer.resolve(snap.val());
            });
            return defer.promise;
          },
          getAll: function() {
            var defer = $firebaseUtils.defer();
            this._itemsRef.on('value', function(snapshot) {
              defer.resolve(snapshot.val());
            });
            return defer.promise;
          },
          distance: function(loc1, loc2) {
            return GeoFire.distance(loc1, loc2);
          },
          updateQuery: function(queryCriteria) {
            //TODO test if sync is destroyed
            this._query = this._sync.updateQuery(queryCriteria);
          },
          stopCallbacks: function() {
            _.each(this._observers, function(callback) {
              callback.cancel();
            });
            this._observers = [];
          },
          on: function(eventType, callback) {
            if (this._query !== undefined) {
              var cb = this._query.on(eventType, callback);
              this._observers.push(cb);
              return cb;
            }
          }
        };

        function QueryArraySync(geofireArray) {
          function init(list) {
            _list = list;
          }

          //TODO remove if not used
          function destroy() {
            if (!sync.isDestroyed) {
              sync.isDestroyed = true;
              _.each(_callbackRegister, function(cb) {
                cb.cancel();
              });
            }
          }

          function onKeyEntered(key, location, distance) {
            return geofireArray.getById(key)
              .then(function(data) {
                var index = _.findIndex(_list, function(item) {
                  return item.id === key;
                });
                if (index !== -1) {
                  return;
                }
                data.location = location;
                data.distance = distance;
                _list.push(data);
              });
          }

          function onKeyExited(key) {
            var index = _.findIndex(_list, function(item) {
              return item.id === key;
            });
            if (index !== -1) {
              _list.splice(index, 1);
            }
          }

          function updateQuery(queryCriteria) {
            if (_query !== null) {
              _query.updateCriteria(queryCriteria);
            } else {
              _query = geofireArray._geofire.query(queryCriteria);
              _callbackRegister.push(_query.on('key_entered', onKeyEntered));
              _callbackRegister.push(_query.on('key_exited', onKeyExited));
            }
            return _query;
          }

          var _list;
          var _query = null;
          var _callbackRegister = [];

          var sync = {
            init: init,
            destroy: destroy,
            isDestroyed: false,
            updateQuery: updateQuery
          };

          return sync;
        }

        return new GeofireService();
      }
    ];
  });
})();

使用此解决方案,我们可以创建具有_geofire位置的项目,更新它们,检索所有项目并维护使用updateQuery方法设置的查询中的项目数组。

受到弗兰克回答的启发!

相关问题