navigator.geolocation.getCurrentPosition иногда работает, иногда не - PullRequest
201 голосов
/ 03 августа 2010

Итак, у меня есть довольно простой 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

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

Ответы [ 22 ]

323 голосов
/ 07 октября 2010

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

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

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

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

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

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

На работе, однако, я наблюдаю довольно странные изменения в поведении: геолокация работает на некоторых компьютерах все время (за исключением IE, конечно), другие работают только в chrome и safari, но не в firefox (проблема геккона?), Другие работают один раз затем произойдет сбой - и шаблон меняется с часа на час, изо дня в день. Иногда у вас есть «счастливый» компьютер, иногда нет. Возможно, поможет убой коз в полнолуние?

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

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

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

64 голосов
/ 01 декабря 2011

Это хакерский способ обойти это, по крайней мере, он работает во всех текущих браузерах (в 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();
}

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

Неуклюжий, но он работает.

37 голосов
/ 10 мая 2012

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

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

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

13 голосов
/ 11 сентября 2010

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

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

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

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

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

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

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

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

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

ура.

12 голосов
/ 10 августа 2015

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

//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 голосов
/ 10 декабря 2010

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

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

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

Рекомендую внимательно следить за вашими ошибками. Быть ожидаемым для всего. Есть план резервного копирования для всего. Я сам использую некоторые значения по умолчанию или значения из своей базы данных на случай, если не удастся как геолокации Google, так и геолокации навигатора.

5 голосов
/ 13 июня 2017

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

5 голосов
/ 30 января 2013

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

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}
        )
    }       
}

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

4 голосов
/ 10 февраля 2012

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

  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);
3 голосов
/ 28 октября 2015

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

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

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

...