Я новичок в Firebase + GeoFire, и у меня проблемы с функцией запроса geoFire.
Я хочу добавить в массив результаты из функции geoQuery и вернуть ее в функцию. Но данные, которые я манипулирую внутри метода geoQuery.on
выглядят вне видимости или недоступны или из-за обещаний, я не знаю... факт находится вне метода geoquery.on, продавцы переменных пустые.
Как я могу вернуть результаты из geoQuery и сохранить его в возвращаемой переменной
//Set seller position in firebase db
var setPosition = function() {
navigator.geolocation.getCurrentPosition(setPositionSuccess, error, options);
//navigator.geolocation.watchPosition(setPositionSuccess, positionError, { enableHighAccuracy:true })
};
//Get sellers near buyer position
var getSellersForCurrentPosition = function() {
navigator.geolocation.getCurrentPosition(getPositionSuccess, error, options);
//navigator.geolocation.watchPosition(positionSuccess, positionError, { enableHighAccuracy:true })
};
//Callback function from html 5 geo api
function getPositionSuccess(pos) {
var crd = pos.coords;
var currentPosition = [crd.latitude, crd.longitude];
// Query radius
var radiusInKm = 2;
var firebaseRef = new Firebase(FBURL + "/geofire/sellers/");
var geoFire = new GeoFire(firebaseRef);
var geoQuery = geoFire.query({
center: currentPosition,
radius: radiusInKm
});
var sellers = [];
var oneSeller = {};
var onKeyEnteredRegistration = geoQuery.on("key_entered", function(key, location, distance) {
oneSeller = {
id: key,
distance: distance,
location: location
};
sellers.push(oneSeller);
});
var onReadyRegistration = geoQuery.on("ready", function() {
geoQuery.cancel();
});
return sellers;
}
Кстати, насколько точна геолокация html5? Различие между браузером рабочего стола и мобильным браузером?
Geofire контролирует продавцов в указанном вами диапазоне. В любое время, когда продавец входит/выходит из диапазона, он запускает key_entered
или key_exited
. Эти события могут произойти в любое время после запуска запроса. В условиях JavaScript это часто описывается как: обратные вызовы происходят асинхронно.
Простой поток событий может объяснить, что происходит лучше всего:
getPositionSuccess()
geoFire.query()
getPositionSuccess()
функция getPositionSuccess()
и завершаетсяkey_entered
и выполняет обратный вызовgetPositionSuccess()
уже вышел, так как он может вернуть значение?Даже если вы должны были дождаться, когда первый продавец войдет в диапазон до возвращения (возможно, в браузере, но это возможно в других языках/средах), как вы вернете значение, когда второй продавец входит в диапазон?
По этой причине вам приходится иметь дело с асинхронными данными по-разному. Обычно вы делаете это, перемещая код, который вызовет getPositionSuccess()
в функцию.
Скажите, что вы сейчас пытаетесь это сделать:
var sellers = getPositionSuccess(pos);
sellers.forEach(function(seller) {
addSellerToMap(seller);
});
Чтобы обрабатывать асинхронный характер событий, вы переместите этот код в getPositionSuccess
:
//Callback function from html 5 geo api
function getPositionSuccess(pos) {
var crd = pos.coords;
var currentPosition = [crd.latitude, crd.longitude];
// Query radius
var radiusInKm = 2;
var firebaseRef = new Firebase(FBURL + "/geofire/sellers/");
var geoFire = new GeoFire(firebaseRef);
var geoQuery = geoFire.query({
center: currentPosition,
radius: radiusInKm
});
var oneSeller = {};
geoQuery.on("key_entered", function(key, location, distance) {
oneSeller = {
id: key,
distance: distance,
location: location
};
addSellerToMap(oneSeller);
});
}
Я понимаю, что в вашем случае использования ваши продавцы не будут двигаться, поэтому может быть более интуитивно понятно, что они представляют собой статический список. Но даже в этом случае результаты загружаются из удаленной базы данных, и до загрузки этих данных потребуется некоторое время. Современная сеть загружает данные асинхронно, и весь ваш код будет иметь дело с этим способом, подобным тому, что я изложил выше.
addSellerToMap
вы также можете поместитьtellBuyerThatASellerWasFound
.