我将firebase与GeoFire,AngularFire和常规JavaScript API结合使用。
在我的应用程序中,GeoQuery通过订阅.on("key_entered")
事件返回对象键列表。然后我可以使用.once()
查询方法获取对象。但是,我真正需要做的是有一个synchronized数组,其中包含GeoQuery返回键的对象。我还需要通过createdAt
时间戳来限制/订购这些时间戳,以免下载每个对象。当新对象点击我的.on("key_entered")
事件时,应将它们添加到数组中。
经过大量的研究,我无法弄清楚如何做到这一点。可能吗?如果没有,那么对我来说这是解决这个问题的最佳途径。
答案 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方法设置的查询中的项目数组。
受到弗兰克回答的启发!