У меня есть карта листовки, в которой map.locate() можно вызвать двумя способами: 1. Кнопка местоположения Easybutton, 2. Обычный вызов каждую минуту с помощью setTimeout.
У каждого есть свой собственный слушатель locationfound, или, по крайней мере, я бы хотел, чтобы они были — вот в чем проблема: нажатие на кнопку easybutton вызывает как прослушиватель control._map.on('locationfound'..) easybutton, так и слушатель map.on('locationfound'..) внутри getLocation().
Обычный вызов getLocation() запускает только прослушиватель map.on('locationfound'..).
Это как-то связано с масштабом?
Как мне сделать так, чтобы easybutton запускал только предполагаемого прослушивателя, а вызов setTimeout для map.locate() запускал только прослушиватель в getLocation()?
L.easyButton({
position: easy_position,
states:[
{
stateName: 'unloaded',
icon: 'fa-location-arrow',
title: 'load image',
onClick: function(control){
control.state("loading");
control._map.on('locationfound', function(e){
alert('location found - easybutton');
this.setView(e.latlng,18); // go to current location
control.state('loaded');
setTimeout(function(){
control.state('unloaded');
}, 3000);
});
control._map.on('locationerror', function(){
control.state('error');
setTimeout(function(){
control.state('unloaded');
}, 3000);
});
control._map.locate();
setTimeout(function(){
control.state('unloaded');
}, 10000); // give it ten seconds to find the location
}
}, {
stateName: 'loading',
icon: 'fa-spinner fa-spin'
}, {
stateName: 'loaded',
icon: 'fa-thumbs-up'
}, {
stateName: 'error',
icon: 'fa-frown-o',
title: 'location not found'
}
]
}).addTo(map);
function updateLocation() {
getLocation(false);
setTimeout(updateLocation, 60000);
}
getLocation = function(goToLocation) {
map.on('locationfound', function(e) {
alert('location found - getLocation()');
var lat = e.latitude;
var lng = e.longitude;
if (goToLocation) {
pan_to(lat,lng,0.5);
}
});
map.on('locationerror', function(e) {
console.info(e);
});
map.locate({
setView: false,
maxZoom: 16
});
}



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы можете смягчить свою проблему, используя map.once() метод для присоединения ваших прослушивателей событий (как в вашем обычном процессе, так и в вашей кнопке), чтобы они удалялись после однократного срабатывания:
Behaves as
on(…), except the listener will only get fired once and then removed.
Есть еще некоторые временные ситуации, когда оба слушателя могут быть запущены одновременно: если ваша кнопка нажата, когда ваш обычный процесс инициировал местоположение, но результат еще не получен, или наоборот.
К сожалению, Leaflet не различает вызовы метода map.locate(). Отсюда предложение @IvanSanchez напрямую использовать API браузера.
Вы можете устранить эти переходные ситуации, управляя флагом/мьютексом всякий раз, когда вы запускаете местоположение, а не выполняете другой или откладываете его, если ваш мьютекс заблокирован.
Подходы map.once() и flag кажутся вполне удовлетворительными. Мне было интересно, может ли быть более элегантное решение, связанное с областями. Что касается решения API браузера - я не вижу, как это меняет фундаментальную проблему? Что можно сделать с API браузера, чего нельзя сделать с помощью листовки?
Более креативное решение, которое, можно сказать, ближе к использованию прицелов, может состоять в том, чтобы использовать фиктивную карту только для другого места.
С API браузера вы указываете действие непосредственно как обратный вызов, поэтому вы также можете сказать, что он использует области. Тогда как с Листовкой нужно проходить события, а информации по разным источникам нет.
Рассмотрите возможность прямого использования API геолокации браузера. См. developer.mozilla.org/en-US/docs/Web/API/Geolocation_API/…