Navigator.geolocation.getCurrentPosition иногда работает иногда не

Итак, у меня есть довольно простой бит JS, использующий jammy navigator.geolocation.getCurrentPosition.

$(document).ready(function(){
  $("#business-locate, #people-locate").click(function() {
    navigator.geolocation.getCurrentPosition(foundLocation, noLocation);
  });

  navigator.geolocation.getCurrentPosition(foundLocation, noLocation);

  function foundLocation(position) {
    var lat = position.coords.latitude;
    var lon = position.coords.longitude;
    var userLocation = lat + ', ' + lon;
    $("#business-current-location, #people-current-location").remove();
    $("#Near-Me")
      .watermark("Current Location")
      .after("<input type='hidden' name='business-current-location' id='business-current-location' value='"+userLocation+"' />");
    $("#people-Near-Me")
      .watermark("Current Location")
      .after("<input type='hidden' name='people-current-location' id='people-current-location' value='"+userLocation+"' />");
  }
  function noLocation() {
    $("#Near-Me").watermark("Could not find location");
    $("#people-Near-Me").watermark("Could not find location");
  }
})//end DocReady

В основном, что происходит здесь, мы получаем текущую позицию, если она получена, два "водяных знака" помещаются в два поля, которые говорят "Текущая позиция", и два скрытых поля создаются с использованием данных lat-long в качестве их значения (они сначала удаляются, поэтому они не получают дублирования каждый раз). Есть также две кнопки, которые имеют функцию щелчка, привязанную к ним, которые делают то же самое. К сожалению, каждый третий раз или около того, он работает. Какая проблема здесь?

Ответы

Ответ 1

У меня была ровно та же проблема, и мы почти не находили информацию в Интернете об этом. В книгах ничего нет. Наконец, я нашел этот трезвый запрос в stackoverflow и (ha!), Это был последний импульс, который мне нужно было создать здесь.

И у меня есть частичный ответ, но, увы, не полный.

Прежде всего, убедитесь, что время ожидания по умолчанию для getCurrentPosition бесконечно (!). Это означает, что ваш обработчик ошибок будет никогда не называться, если getCurrentPosition находится где-то на задней панели.

Чтобы гарантировать, что вы получите тайм-аут, добавьте дополнительный третий параметр к вашему вызову getCurrentPosition, например, если вы хотите, чтобы пользователь подождал не более 10 секунд, прежде чем дать им понять, что происходит, используйте:

navigator.geolocation.getCurrentPosition(successCallback,errorCallback,{timeout:10000});

Во-вторых, я испытал совершенно другую надежность в разных контекстах. Здесь, дома, я получаю обратный вызов в течение секунды или двух, хотя точность низкая.

На работе, однако, я испытываю довольно необычные вариации в поведении: Geolocation работает на некоторых компьютерах все время (IE исключен, конечно), другие работают только в хроме и сафари, но не в firefox (проблема gecko?), другие работают один раз, затем сбой - и образец меняется от часа к часу, изо дня в день. Иногда у вас есть "удачливый" компьютер, иногда нет. Может быть, убойные козы в полнолуние помогут?

Мне это не удалось понять, но я подозреваю, что инфраструктура back end более неравномерна, чем рекламируемая в различных gung-ho-книгах и веб-сайтах, которые продвигают эту функцию. Мне очень жаль, что они будут немного более откровенными о том, насколько это чертовски эта функция, и насколько важна эта настройка тайм-аута, если вы хотите, чтобы ваш обработчик ошибок работал правильно.

Сегодня я пытался научить этот материал студентам и имел смущающую ситуацию, когда мой собственный компьютер (на проекторе и несколько больших экранов) терпел неудачу, тогда как около 80% студентов получали результат почти мгновенно (с использованием той же самой беспроводной сети). Очень сложно решить эти проблемы, когда мои ученики также делают опечатки и другие промахи, и когда мой собственный компьютер также терпит неудачу.

В любом случае, надеюсь, это поможет некоторым из вас, ребята. Спасибо за проверку работоспособности!

Ответ 2

Это хакерский способ, которым я обойду это, по крайней мере, он работает во всех существующих браузерах (в Windows у меня нет Mac):

if (navigator.geolocation) {
    var location_timeout = setTimeout("geolocFail()", 10000);

    navigator.geolocation.getCurrentPosition(function(position) {
        clearTimeout(location_timeout);

        var lat = position.coords.latitude;
        var lng = position.coords.longitude;

        geocodeLatLng(lat, lng);
    }, function(error) {
        clearTimeout(location_timeout);
        geolocFail();
    });
} else {
    // Fallback for no geolocation
    geolocFail();
}

Это также будет работать, если кто-то нажимает кнопку "закрыть" или не выбирает "нет" или выбирает параметр "Никогда еще Share" в Firefox.

Clunky, но он работает.

Ответ 3

Это работает для меня каждый раз:

navigator.geolocation.getCurrentPosition(getCoor, errorCoor, {maximumAge:60000, timeout:5000, enableHighAccuracy:true});

Хотя это не очень точно. Самое смешное, что на том же устройстве, если я запустил это, он откладывает меня примерно на 100 метров (каждый раз), но если я пойду на карты Google, он точно найдет мое местоположение. Поэтому, хотя я думаю, что enableHighAccuracy: true помогает ему работать последовательно, это, похоже, не делает его более точным...

Ответ 4

То же самое происходит с людьми, это прекрасно работает в Chrome (стабильный, dev и canary), а не в FF и Safari. Он также отлично работает на моем iPhone и iPad (Safari!). Это может быть связано с относительной новизностью этой функции (т.е. Это ошибка). Я трачу почти неделю на это сейчас, и я просто не могу заставить его работать над этими браузерами.

Вот что я нашел:

При первом вызове getCurrentPosition он работает отлично. Любой последующий вызов никогда не возвращается, т.е. Он не запускает функции successCallback или errorCallback. Я добавил несколько вариантов позиции к моему призыву, чтобы доказать свою точку зрения:

 navigator.geolocation.getCurrentPosition(successCallback, errorCallback,  {timeout: 10000});

и он время от времени каждый раз (после первого успешного вызова). Я думал, что могу исправить это с максимумомAge, но это, похоже, не работает, так как предполагается, что он будет работать:

navigator.geolocation.getCurrentPosition(successCallback, errorCallback,  {maximumAge:60000, timeout: 2000});

это должно предотвращать фактическое вызов функции getCurrentPosition, если вы вызываете ее в течение 60 секунд, но она игнорирует это (однако это может быть связано с тем, что я действительно обновляю свою страницу для запуска второго вызова, не уверен, что это постоянное по отношению к вызовам )

btw, даже примеры Google не работают в этих браузерах, что заставляет меня думать, что это действительно ошибки браузера, попробуйте, загрузите его дважды в Safari, и он не будет работать во второй раз.

Если кто-нибудь найдет решение для этого, ПОЖАЛУЙСТА, дайте мне знать: -)

Приветствия.

Ответ 5

Это уже старый вопрос, но все ответы не помогли решить мою проблему, поэтому добавьте тот, который я нашел. Он пахнет хаком (и он один), но всегда работает в моей ситуации. Надеюсь, что и в вашей ситуации.

//Dummy one, which will result in a working next statement.
navigator.geolocation.getCurrentPosition(function () {}, function () {}, {});
//The working next statement.
navigator.geolocation.getCurrentPosition(function (position) {
    //Your code here
}, function (e) {
    //Your error handling here
}, {
    enableHighAccuracy: true
});

Ответ 6

Вы не получите сообщение об ошибке, поскольку по умолчанию он не имеет таймаута (по крайней мере, я думаю). У меня была такая же проблема с firefox только для меня, firefox всегда дает тайм-аут. Вы можете установить тайм-аут самостоятельно, как это.

Я установил максимальный возраст Infinity, чтобы убедиться, что это не проблема. Моя функция отлично работает в chrome, но я получаю тайм-аут каждый раз в firefox.

    navigator.geolocation.getCurrentPosition(
        function(position) {
            //do succes handling
        },
        function errorCallback(error) {
            //do error handling
        },
        {
            maximumAge:Infinity,
            timeout:5000
        }
    );

Я рекомендую внимательно следить за вашими ошибками. Ожидайте всего. У вас есть резервный план для всего. Я использую некоторые значения или значения по умолчанию из моей базы данных в случае сбоя геолокации google и геолокации навигатора.

Ответ 7

Итак, я столкнулся с тем же. Я пробовал решение тайм-аута, которое работало, но не надежно. Я обнаружил, что если вы просто назовете это дважды, местоположение будет исправлено правильно

function getLocation(callback)
{   
    if(navigator.geolocation)
    {
        navigator.geolocation.getCurrentPosition(function(position)
        {
            navigator.geolocation.getCurrentPosition(callback, function(){},{maximumAge:0, timeout:10000});
        },function(){}, {maximumAge:0, timeout:10000});
    }
    return true;
}

это, конечно, немного медленнее, но у меня не было того, чтобы однажды я получил неправильную позицию. Я несколько раз ударил тайм-аут и не возвращал ничего, кроме другого, что он отлично работает. Я знаю, что это все еще немного взломанно, и я с нетерпением жду, чтобы кто-то нашел реальное решение.

Или, если вы хотите убедиться, что он будет продолжать пытаться, пока вы не захотите сдаться, вы можете попробовать что-то вроде этого.

//example
$(document).ready(function(){
    getLocation(function(position){
        //do something cool with position
        console.log(position);
    });
});


var GPSTimeout = 10; //init global var NOTE: I noticed that 10 gives me the quickest result but play around with this number to your own liking


//function to be called where you want the location with the callback(position)
function getLocation(callback)
{   
    if(navigator.geolocation)
    {
        var clickedTime = (new Date()).getTime(); //get the current time
        GPSTimeout = 10; //reset the timeout just in case you call it more then once
        ensurePosition(callback, clickedTime); //call recursive function to get position
    }
    return true;
}

//recursive position function
function ensurePosition(callback, timestamp)
{
    if(GPSTimeout < 6000)//set at what point you want to just give up
    {
        //call the geolocation function
        navigator.geolocation.getCurrentPosition(
            function(position) //on success
        {
                //if the timestamp that is returned minus the time that was set when called is greater then 0 the position is up to date
            if(position.timestamp - timestamp >= 0)
                {
                    GPSTimeout = 10; //reset timeout just in case
                    callback(position); //call the callback function you created
                }
                else //the gps that was returned is not current and needs to be refreshed
                {
                    GPSTimeout += GPSTimeout; //increase the timeout by itself n*2
                    ensurePosition(callback, timestamp); //call itself to refresh
                }
            },
            function() //error: gps failed so we will try again
            {
                GPSTimeout += GPSTimeout; //increase the timeout by itself n*2
                ensurePosition(callback, timestamp);//call itself to try again
            },
            {maximumAge:0, timeout:GPSTimeout}
        )
    }       
}

У меня, вероятно, есть несколько типов и некоторые орфографические ошибки, но я надеюсь, что вы поняли эту идею. Дайте мне знать, есть ли у кого-нибудь вопросы или кто-то находит что-то лучше.

Ответ 8

Я все еще получаю точные результаты в 2017 году, и у меня есть теория: в документации API говорится, что вызов теперь доступен только "в безопасном контексте", то есть через HTTPS. У меня проблемы с получением результата в моей среде разработки (http на localhost), и я считаю, что именно поэтому.

Ответ 9

вот мое решение благодаря закрытию:

  function geoloc(success, fail){
    var is_echo = false;
    if(navigator && navigator.geolocation) {
      navigator.geolocation.getCurrentPosition(
        function(pos) {
          if (is_echo){ return; }
          is_echo = true;
          success(pos.coords.latitude,pos.coords.longitude);
        }, 
        function() {
          if (is_echo){ return; }
          is_echo = true;
          fail();
        }
      );
    } else {
      fail();
    }
  }

  function success(lat, lng){
    alert(lat + " , " + lng);
  }
  function fail(){
    alert("failed");
  }

  geoloc(success, fail);

Ответ 10

Для тех, кто работает в приложении iPhone...

Если ваш код работает в UIWebView на iOS 9+, тогда вы должны установить NSLocationWhenInUseUsageDescription в свой план приложения.

Если вы не установите его, то getCurrentPosition никогда не перезвонит, и пользователь никогда не будет запрошен.

Ответ 11

@brennanyoung ответ велик, но если вам интересно, что делать в случае сбоя, вы можете использовать API геолокации IP, например https://ipinfo.io (это мой сервис). Вот пример:

function do_something(coords) {
    // Do something with the coords here
    // eg. show the user on a map, or customize
    // the site contents somehow
}

navigator.geolocation.getCurrentPosition(function(position) { 
    do_something(position.coords);
    },
    function(failure) {
        $.getJSON('https://ipinfo.io/geo', function(response) { 
        var loc = response.loc.split(',');
        var coords = {
            latitude: loc[0],
            longitude: loc[1]
        };
        do_something(coords);
        });  
    };
});

Подробнее см. http://ipinfo.io/developers/replacing-navigator-geolocation-getcurrentposition.

Ответ 12

У меня были похожие проблемы, и мы изучали возможность того, что у браузеров есть ограничения на то, как часто можно вызывать getCurrentPosition. Кажется, я часто могу получить место, но если я сразу обновляю страницу, он будет тайм-аут. Если я немного подожду, я могу снова найти место. Обычно это происходит с FF. В Chrome и Safari я еще не заметил, что время ожидания getCurrentPosition. Просто мысль...

Хотя я не могу найти какую-либо документацию для поддержки этого, это был вывод, который я пришел после долгих испытаний. Возможно, у кого-то еще есть информация об этом?

Ответ 13

Наконец-то я нашел рабочую версию для firefox, chrome и default navigator в android (только 4.2):

function getGeoLocation() {
        var options = null;
        if (navigator.geolocation) {
            if (browserChrome) //set this var looking for Chrome un user-agent header
                options={enableHighAccuracy: false, maximumAge: 15000, timeout: 30000};
            else
                options={maximumAge:Infinity, timeout:0};
            navigator.geolocation.getCurrentPosition(getGeoLocationCallback,
                    getGeoLocationErrorCallback,
                   options);
        }
    }

Ответ 14

Второй параметр, переданный в Geolocation.getCurrentPosition(), - это функция, с которой вы хотите обрабатывать любые ошибки геолокации. Сама функция обработчика ошибок получает объект PositionError с подробными сведениями о том, почему попытка геолокации не удалась. Я рекомендую выводить ошибку на консоль, если у вас есть проблемы:

var positionOptions = { timeout: 10000 };
navigator.geolocation.getCurrentPosition(updateLocation, errorHandler, positionOptions);
function updateLocation(position) {
  // The geolocation succeeded, and the position is available
}
function errorHandler(positionError) {
  if (window.console) {
    console.log(positionError);
  }
}

Выполнение этого в моем коде показало сообщение "Сетевой провайдер местоположения в https://www.googleapis.com/ ': Возвращенный код ошибки 400". Оказывается, Google Chrome использует API Google, чтобы получить местоположение на устройствах, на которых нет встроенного GPS (например, большинство настольных компьютеров). Google возвращает приблизительную широту/долготу на основе IP-адреса пользователя. Однако в сборках разработчиков Chrome (таких как Chromium on Ubuntu) нет ключа доступа к API, включенного в сборку браузера. Это приведет к сбою запроса API. См. Chromium Issue 179686: Geolocation с сообщением 403 для деталей.

Ответ 15

Я обнаружил, что этот способ не работает

navigator.geolocation.getCurrentPosition(function() {...}, function(err) {...}, {});

Но

этот способ работает идеально

function storeCoordinates(position) {
    console.log(position.coords.latitude, position.coords.longitude);
}    

function errorHandler() {...}

navigator.geolocation.getCurrentPosition(storeCoordinates, errorHandler, { enableHighAccuracy: true, timeout: 20000, maximumAge: 0 });

Ответ 16

У меня эта проблема в Mozilla. Все время: Ошибка: неизвестная позиция при обнаружении ошибки.

Теперь я использую 47 Mozilla. Я пробовал все, но все время эта проблема. НО, затем откройте about: config в моей добавочной строке, перейдите geo.wifi.ui и измените его значение на " https://location.services.mozilla.com/v1/geolocate?key=test". работает!

Если u имеет Ошибка определения местоположения, попробуйте увеличить значение тайм-аута:

var options = {
  enableHighAccuracy: true,
  timeout: 5000,
  maximumAge: 0       
};
navigator.geolocation.getCurrentPosition(success, error, options);

Ответ 17

Может быть хорошей идеей использовать службу геоопределения IP-адреса в качестве резервного метода, если getCurrentPosition не работает. Например, с нашим api https://ip-api.io

$.getJSON("http://ip-api.io/json/",
    function(result) {
        console.log(result);
    });

Ответ 18

Я отправлю это здесь, если это будет полезно для всех...

В iOS Safari вызовы navigator.geolocation.getCurrentPosition будут отключены, если у меня была активная функция navigator.geolocation.watchPosition.

Запуск и остановка watchPosition с использованием clearWatch(), как описано здесь, сработало: https://developer.mozilla.org/en-US/docs/Web/API/Geolocation/watchPosition

Ответ 19

Недавно я заметил эту проблему, и я не уверен, как это происходит, но иногда появляется, что firefox зацикливается на чем-то, загруженном в кеш. После очистки кеша и перезапуска firefox он снова функционирует.

Ответ 20

В этой библиотеке добавлена ​​опция желаемого качества и максимальной ожидания для вызовов геолокации, что означает, что она будет пытаться получить позицию, пока точность не окажется в пределах указанный диапазон.

Ответ 21

Спасибо всем за их вклад, это помогло мне.

В дополнение к использованию функции watchPosition() вместо getCurrentPosition() я также обнаружил, что мне нужно переместить вызов из документа document.ready() в голову.

Ответ 22

В нашем случае это всегда работает с первого раза, но при повторном запуске функции более 3-4 раз происходит сбой.

Простой обходной путь: сохраните его значение в LocalStorage.

До:

navigator.geolocation.getCurrentPosition((position) => {
  let val = results[0].address_components[2].long_name;
  doSthWithVal(val);      
}, (error) => { });

После:

if(localStorage.getItem('getCurrentPosition') !== null) {
  doSthWithVal(localStorage.getItem('getCurrentPosition'));
}
else {
  navigator.geolocation.getCurrentPosition((position) => {
      let val = results[0].address_components[2].long_name;
      localStorage.setItem('getCurrentPosition',val);
      doSthWithVal(val);      
  }, (error) => { });
}