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


220

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

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


Может быть, определить функции, прежде чем использовать их.
tcooc

4
@digitalFresh, это не должно иметь значения, потому что анализатор JS ищет эти объявления до того, как код начинает выполняться
antimatter15

Возможно ли, что использование jQuery там вызывает проблемы?
theassociatedweb

1
Что именно вы имеете в виду, когда говорите, что иногда это не работает? Является ли noLocationвызывается функция? Если это так, вы можете добавить errorпараметр, noLocation()а затем error.codeи error.messageможет помочь вам в отладке. Это также может помочь нам узнать, какой браузер вы используете, и если вы видите ту же проблему в разных браузерах.
npdoty

Я имею в виду, что иногда это дает мне долготу, а иногда нет. когда он не работает, он даже не выдает сообщение «невозможно найти местоположение», поэтому бит noLocation также не запускается.
theassociatedweb

Ответы:


342

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

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

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

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

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

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

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

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

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

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


5
Хорошая подробная информация, спасибо! Я вижу те же проблемы, но только на Firefox 3.6.13. Хром вроде бы довольно надежный.
Фелипе Лима

Здесь то же самое, и параметр MaximumAge, похоже, тоже ненадежен. Спасибо за пост.
Ричард

1
Хороший, у меня была та же проблема (на Samsung Galaxy Tab, 10.1, под управлением Android 4.0.3 ), как только я использовал параметр тайм-аута выше, я смог решить эту проблему.
mlo55

9
Важно понять, в чем заключается timeoutопция getCurrentPosition(). Это не время для пользователя, чтобы разрешить или отклонить запрос геолокации, но сколько времени сети может потребоваться, чтобы вернуть местоположение после предоставления разрешения. Если пользователь не отвечает на запрос геолокации, обработчик ошибок никогда не будет вызван. Таким образом, вам нужен второй тайм-аут, как в ответе @ xiaohouzi79.
Франсуа

2
убой коз в полнолуние поможет? LOL
Asim KT

66

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

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


1
+1 Но вам не хватает geolocFail();обработчика ошибок и getcodeLatLng();геокодера.
Кайзер

Сладкий - таймер работает прекрасно, если кто-то решит не делиться местоположением. Некоторые браузеры не играют хорошо, когда пользователи делают это. Этот обходной таймер отлично работал на моем плагине Store Locator Plus WP!
Ланс Кливленд

2
@sajith - Не уверен, что это решение устарело с недавними браузерами FF. Это сработало в то время, когда я предоставил решение, потому что оно было нужно для сайта, над которым я работал. Вы проверяли?
собирается

извините, это сработало. Но я не могу найти то, что заставляет его работать. После закрытия и повторного открытия FF, его работающий ........ спасибо за ваше решение ....
Sajith

1
Вы не должны использовать функцию внутри строки. Злой Eval работает там без всякого сомнения. setTimeout ("geolocFail ()", 10000);
17

42

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

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

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


Это остановило firefox от отклонения запроса и отправки обратно объекта тайм-аута.
Тони

В 100 метрах от меня находится сотовая вышка, к которой я привязан. Так что он возвращает местоположение сотовой вышки, а не мой телефон. Может быть точнее, если бы я был снаружи, чтобы gps
заработал

9
Он отодвигает вас на пару метров, потому что у вас установлен максимальный возраст 60 секунд. Таким образом, ваше местоположение находится там, где вы были 60 секунд назад. Установите MaximumAge на 10 секунд или меньше (MaximumAge: 10000) и повторите попытку.
Роберт Смит

Я использовал это getCurrentPosition в Angular Resolver, который возвращает Observable. Resolver только завершен с перерывами. Добавление этих параметров: {maximumAge: 60000, timeout: 5000, enableHighAccuracy: true} заставляло это работать каждый раз !!!
Мутоно

17

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

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

3
Это самый хакерский из хаков, и я понятия не имею, как ты даже подумал попробовать, но это решает мою проблему. Спасибо!
Бретт Грегсон

Я использовал это сам в некоторых случаях. Вторая попытка всегда работает лучше в моем опыте
Нико Вестердейл

13

Те же самые люди, это прекрасно работает между прочим в 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 секунд, но она игнорирует это (однако, это может быть связано с тем, что я фактически обновляю свою страницу, чтобы вызвать второй вызов, не уверенный, является ли это постоянным во всех вызовах)

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

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

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


У меня точно такая же проблема, как и у вас, она работает для первого вызова, но не для следующих, если кто-нибудь найдет решение, которое я бы очень заинтересовал ... @ xiaohouzi79 ваше решение заканчивается каждый раз (кроме первого) в geolocFail ( )
Адриано Риццо

8

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

Моя функция прекрасно работает в Chrome, но в Firefox я получаю тайм-аут.

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

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


7
просто FYI, MaximumAge относится к возрасту данных о местоположении в кеше, а установка его в бесконечность гарантирует, что вы получите кешированную версию. Установка его в 0 заставляет устройство восстанавливать позицию.
Porco

отрицательно, потому что MaximumAge: Infinity облажает вас, как указано выше, что означает принудительное использование кэшированного значения.
13

7

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


Хм интересно. Даже в 2020 году все еще не работает HTTPS на локальном хосте!
NitroStoutPlz

6

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

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

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


1
Огромное спасибо. Это было решением для меня.
Цинь Чжэнцюань

5

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

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

Это сработало для меня в реакции на родной язык navigator && navigator.geolocation
Ашиш Сингх Рават

5

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

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

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

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

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


3

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

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

4
В чем разница между обоими?
Пардип Джейн

Анонимная функция против именованного
1стинкт

действительно большие различия. спасибо, это тоже не работает
одного

3

Ответ @ 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);
        });  
    };
});

См. Https://ipinfo.io/developers/replacing-getcurrentposition для получения более подробной информации.


Вот исправленная ссылка на это: ipinfo.io/developers/replacing-getcurrentposition
Peater

5
Грозный. Точность составляет 5-7 миль от реальной позиции в США и Канаде и 100 миль где-то в России.
ekashking

1
Для многих приложений это хорошо - и намного лучше, чем не знать, каково местоположение.
Бен Доулинг,

это не работает нигде. Каждый запрос получает неправильную долготу и широту
одного

Что вы имеете в виду под неправильным? У вас есть примеры?
Бен Доулинг

2

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

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


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

Я не видел ни одного случая, когда браузер ограничивал бы количество звонков на услуги определения местоположения. Как часто вы спрашиваете?
Нико Вестердейл

2

Наконец-то я нашел рабочую версию для Firefox, Chrome и стандартного навигатора в 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);
        }
    }

2

Второй передаваемый параметр 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 в Ubuntu) ключ сборки API не включен в сборку браузера. Это приводит к тому, что запрос API завершается неудачно. См. Chromium Issue 179686: Геолокация с ошибкой 403 для получения более подробной информации.


1

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

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

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

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

1

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

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

1

В нашем случае это всегда работает с первого раза, но при повторном запуске функции более 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) => { });
}

0

Я сам недавно заметил эту проблему, и я не уверен, как она возникает, но иногда кажется, что Firefox застревает на чем-то загруженном в кеш. После очистки кеша и перезапуска Firefox он снова работает.


0

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


0

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

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


0

Это случилось со мной при использовании адаптивного режима дизайна Firefox. Был подан отчет об ошибке . Пока не используйте режим адаптивного дизайна при использовании API Geolocation.


0

Может быть, это кому-то поможет, на Android у меня возникла та же проблема, но я решил ее, используя setTimeout внутреннюю часть, document.ready чтобы она работала для меня. Во-вторых, нужно увеличить тайм-аут, только если пользователь разрешил свое местоположение через несколько секунд, поэтому я сохранил его до 60000 мили (1 минута), позволяющие вызывать мою функцию успеха, если пользователь нажимает кнопку разрешения в течение 1 минуты.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.