функция сбой никогда не вызывается, если пользователь отказывается поделиться геолокацией в Firefox - PullRequest
47 голосов
/ 10 мая 2011

Итак, у меня есть этот код JavaScript.В Safari и Chrome, если пользователь отказывается поделиться местоположением, он перестает работать, как и должно быть;однако в Firefox это не так.

Любая помощь приветствуется.

function initGeolocation()
{
    if( navigator.geolocation )
    {          
          // Call getCurrentPosition with success and failure callbacks
          navigator.geolocation.getCurrentPosition( success, fail );
    }
    else
    {
          alert("Sorry, your browser does not support geolocation services.");
    }
}

 var map;
 function success(position)
 {

     var longIDText = document.getElementById('longID');
     var latIDText = document.getElementById('latID');
     longIDText.value = position.coords.longitude;
     latIDText.value = position.coords.latitude;
     document.getElementById('coordSubmitID').click();
  }

  function fail(error)
  {
          alert("FAAAAAAAAAAIIIIIIIIIL")
          var zip_code ;
          while (true){
              // Could not obtain location

              zip_code = prompt("Please enter your current address or zip code","");


              if ( zip_code == "" ) {
                  alert(zip_code +" is not a valid address. Please try again.");
              } 
              else{
                break;
              }
          }
          var zipIDText = document.getElementById('zipID');
          zipIDText.value = zip_code;
          document.getElementById('coordSubmitID').click();
  }

Ответы [ 11 ]

29 голосов
/ 10 мая 2011

Для Firefox кажется, что PERMISSION_DENIED повышен только , если выбрано «Никогда не делиться»; если диалоговое окно закрыто или выбрано «Не сейчас», фактически ничего не происходит - даже на демоверсии геолокации mozillas , если вы отклоняете пользовательский интерфейс разрешений, ничего не происходит.

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

https://bugzilla.mozilla.org/show_bug.cgi?id=675533

21 голосов
/ 11 декабря 2012

Это реальная боль, и определенно нежелательная функциональность.

Обходной путь, который я использую, чтобы спасти пользователя, ожидающего вечность, - установить тайм-аут, чтобы проверить, показывает ли счетчик ожидания через 3 секундыи если это так, скрыть его и показать ручной ввод почтового индекса:

var latlng;

var waitTime = 3000;
try {
    if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(function (position) {
            success(position);
        }, showError);
    } else {
        showError("NOT-SUPPORTED");
    }
    var t = setTimeout(function () {
        if ($("#getZip div.loading").css("display") != "none") {
            $("#getZip div.loading").hide();
            $("#errorZip").show();
        }
    }, waitTime);
} catch (evt) {
    alert(evt);
}
13 голосов
/ 08 апреля 2014

Как указал alexleonard, единственное надежное кросс-браузерное решение, которое я нашел для этого, - это иметь setTimeout() для проверки состояния вашего latLng объекта / переменных, как опция timeout для getCurrentPosition() не работает надежно.Приведенный ниже пример был протестирован в IE11, Chrome33 и Firefox28.

Для более полного решения, использующего обещание jQuery, посмотрите мой Гист здесь: https://gist.github.com/GFoley83/10092929

Пример - HitF12, вставьте в консоль и запустите

var latLng,
    geoOptions = {
        enableHighAccuracy: false,
        timeout: 5000, // Wait 5 seconds
        maximumAge: 300000 //  Valid for 5 minutes
    };

var userLocationFound = function(position){
    latLng = {
        lat: position.coords.latitude,
        lng: position.coords.longitude
    };
    window.console.log("User confirmed! Location found: " + latLng.lat + ", " + latLng .lng);
}

var userLocationNotFound = function(){
    latLng = {
        lat: -41.29247, // fallback lat 
        lng: 174.7732  // fallback lng
    };
    window.console.log("Fallback set: ", latLng);
}

window.navigator.geolocation.getCurrentPosition(userLocationFound, userLocationNotFound, geoOptions);

setTimeout(function () {
    if(!latLng){
        window.console.log("No confirmation from user, using fallback");
        userLocationNotFound();
    }else{
        window.console.log("Location was set");
    }
}, geoOptions.timeout + 1000); // Wait extra second
4 голосов
/ 05 марта 2012

Обратите внимание, что на самом деле это также проблема в Chrome.

В Chrome появляется предупреждающее сообщение «сайт хочет узнать ваше местоположение» - тогда в качестве параметров предлагаются «Разрешить» и «Запретить».С дизайном пользовательского интерфейса пользователь, скорее всего, выберет Allow или Deny, который затем вернет ответ функции navigator.geolocation.getCurrentPosition.Однако пользователь также может щелкнуть «X» в правом нижнем углу консультативного уведомления.По сути, это то же самое, что нажать «Не сейчас» в Firefox.

Результат не возвращается функции.

Похоже, таймер должен быть реализован, чтобы учесть этот возможный результат.

4 голосов
/ 04 августа 2011

Это согласно дизайну и, по-видимому, не является проблемой.См. https://bugzilla.mozilla.org/show_bug.cgi?id=675533

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

Обратите внимание, основываясь на комментарии разработчика FF офактическое использование геолокации конечными пользователями, очевидно, разработчики Firefox собирают подробные данные о том, что конечные пользователи делают со своими продуктами.

3 голосов
/ 08 августа 2014

Используйте обещание. Я использую angularjs, у которого есть собственная версия $ q, чтобы решить ту же проблему, что и у всех.

            $scope.ByUserPosition = function () {
                //http://www.w3.org/TR/geolocation-API/
                var deferred = $q.defer();

                deferred.promise.then(findByPosition, function (data) {
                    console.log('error', data);
                });

                var resolveBy = 1000 * 30;
                navigator.geolocation.getCurrentPosition(function (position) {
                    deferred.resolve({ latitude: position.coords.latitude, longitude: position.coords.longitude });
                }, function (err) {
                    deferred.reject(err);
                }, {
                    enableHighAccuracy: true,
                    timeout: resolveBy,
                    maximumAge: 0
                });

                $timeout(function() {
                    deferred.reject('timed out');
                }, resolveBy)
            };
1 голос
/ 25 апреля 2015

Единственное решение этой проблемы заключается в следующем:

  1. Когда пользователь нажимает кнопку, чтобы автоматически определить свое местоположение, показывается счетчик и рядом с ним ссылка "ex: Cancel".
  2. Если он разрешит делиться местоположением, то проблем нет. Если он решит закрыть всплывающее окно Firefox, счетчик будет по-прежнему отображаться, но он может щелкнуть ссылку «Отмена», чтобы остановить счетчик и индикатор для закрытия всплывающего окна

Надеюсь, это поможет:)

1 голос
/ 03 июня 2013

Редактировать (после понижения) 6-11-2013

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

Функция navigator.geolocation.getCurrentPosition () имеет возможность отправить время ожидания вместе с ним:

navigator.geolocation.getCurrentPosition(
     function (position){
        //do someting with position
     },
     function (error){
        // do something with the error (like the code)
     }, 
     {timeout:10000}
);

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

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

поэтому в ответе Джейми я бы сказал:

if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(function (position) {
            success(position);
        }, showError, {timeout:3000});
    }
0 голосов
/ 29 марта 2016

watchPosition и getCurrentPosition принимают второй обратный вызов, который вызывается при возникновении ошибки. Обратный вызов ошибки предоставляет аргумент для объекта ошибки. Для отклоненного разрешения код error.code будет означать error.PERMISSION_DENIED (числовое значение 1).

Подробнее здесь: https://developer.mozilla.org/en/Using_geolocation

Пример:

navigator.geolocation.watchPosition(function(position) {
  console.log("i'm tracking you!");
},
function (error) { 
  if (error.code == error.PERMISSION_DENIED)
     console.log("you denied me :-(");

});

0 голосов
/ 12 июня 2015

Вот решение моей проблемы с использованием vanilla es6 Promises.Вдохновлен ответом @LeblancMeneses.

if(navigator.geolocation) {
  let promise = new Promise((resolve, reject) => {
    navigator.geolocation.getCurrentPosition(
      (position) => {
        resolve(position)
      },
      (error) => {
        resolve(error)
      }
    )
    window.setTimeout(() => {
      resolve({})
    }, 8000)
  })
  promise.then((result) => {
      // do something with result
  })
} else {
  console.log('no geolocation available')
}
...