Обработка ошибок геолокации

Модель работы геолокации в браузере и источники ошибок

Геолокация в веб-приложениях обычно реализуется через navigator.geolocation, который предоставляет асинхронные методы getCurrentPosition и watchPosition. В контексте картографических библиотек этот API интегрируется с компонентами управления местоположением, включая GeolocateControl в MapLibre GL JS.

Ошибки возникают на нескольких уровнях:

  • уровень браузера (разрешения, ограничения устройства)
  • уровень операционной системы (отключённые сервисы определения координат)
  • уровень сети (ошибки получения вспомогательных данных, A-GPS)
  • уровень API (таймауты, недоступность метода)
  • уровень интеграции с картой (необработанные события библиотеки)

Каждый тип ошибки требует отдельной стратегии обработки, поскольку поведение API не унифицировано между устройствами и браузерами.


Основные типы ошибок Geolocation API

Объект ошибки, передаваемый в callback error, содержит поле code, которое определяет тип сбоя:

  • 1 (PERMISSION_DENIED) — пользователь запретил доступ к геолокации
  • 2 (POSITION_UNAVAILABLE) — координаты недоступны
  • 3 (TIMEOUT) — превышено время ожидания

Дополнительно присутствует поле message, которое может отличаться по браузерам и не подходит для логической обработки.


Обработка ошибок через getCurrentPosition

Базовый подход к обработке ошибок заключается в явной передаче error-callback:

navigator.geolocation.getCurrentPosition(
  (position) => {
    const { latitude, longitude } = position.coords;
    console.log('Позиция:', latitude, longitude);
  },
  (error) => {
    switch (error.code) {
      case error.PERMISSION_DENIED:
        console.error('Доступ к геолокации запрещён пользователем');
        break;
      case error.POSITION_UNAVAILABLE:
        console.error('Координаты недоступны');
        break;
      case error.TIMEOUT:
        console.error('Превышено время получения позиции');
        break;
      default:
        console.error('Неизвестная ошибка геолокации');
    }
  },
  {
    enableHighAccuracy: true,
    timeout: 8000,
    maximumAge: 0
  }
);

Ключевой аспект — параметры опций:

  • enableHighAccuracy увеличивает точность, но повышает вероятность таймаутов
  • timeout определяет предел ожидания ответа
  • maximumAge управляет кэшированием предыдущих координат

Интеграция ошибок с GeolocateControl

В MapLibre GL JS геолокация часто используется через контрол:

const geolocate = new maplibregl.GeolocateControl({
  positionOptions: {
    enableHighAccuracy: true,
    timeout: 6000
  },
  trackUserLocation: true,
  showAccuracyCircle: true
});

map.addControl(geolocate);

Контрол генерирует события, позволяющие централизованно обрабатывать ошибки:

  • geolocate
  • error
  • trackuserlocationstart
  • trackuserlocationend

Обработка ошибок выполняется через событие error:

geolocate.on('error', (error) => {
  console.error('Ошибка геолокации:', error);
});

В отличие от чистого navigator.geolocation, здесь ошибка приходит как событие, что требует иной архитектуры обработки.


Причины отказов в разрешениях и стратегия реакции

Наиболее частая ошибка — PERMISSION_DENIED. Она возникает при:

  • первичном отказе пользователя
  • блокировке сайта в настройках браузера
  • использовании небезопасного контекста (HTTP вместо HTTPS)
  • истечении ранее выданного разрешения

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

Типовой подход — перевод интерфейса в режим деградации:

  • отключение автопозиционирования
  • включение ручного выбора точки на карте
  • отображение объясняющего состояния

Таймауты и нестабильные координаты

Ошибка TIMEOUT часто возникает при:

  • слабом GPS-сигнале
  • работе внутри зданий
  • агрессивных настройках enableHighAccuracy
  • блокировке фоновых сервисов геолокации

Практика обработки включает:

  • повторный запрос с увеличенным timeout
  • переключение на менее точный режим
  • использование кэшированных координат (maximumAge > 0)

Пример адаптивной стратегии:

function requestLocation(retry = 0) {
  navigator.geolocation.getCurrentPosition(
    handleSuccess,
    (error) => {
      if (error.code === error.TIMEOUT && retry < 2) {
        requestLocation(retry + 1);
      } else {
        handleGeoError(error);
      }
    },
    {
      enableHighAccuracy: retry === 0,
      timeout: 5000 + retry * 3000,
      maximumAge: retry > 0 ? 60000 : 0
    }
  );
}

POSITION_UNAVAILABLE и деградация качества данных

Ошибка POSITION_UNAVAILABLE связана с невозможностью определить координаты. Причины включают:

  • отсутствие GPS-модуля
  • отключённые сервисы локации
  • работа в закрытых помещениях без Wi-Fi/Cell triangulation
  • ограничения виртуальных сред (emulators, desktop без датчиков)

Реакция системы должна включать fallback:

  • запрос IP-based геолокации (серверная логика)
  • выбор региона вручную
  • использование последней известной позиции

Асинхронная модель watchPosition и накопление ошибок

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

const watchId = navigator.geolocation.watchPosition(
  updatePosition,
  (error) => {
    if (error.code === error.PERMISSION_DENIED) {
      navigator.geolocation.clearWatch(watchId);
    }
    logGeoError(error);
  }
);

Особенность этого режима — необходимость предотвращения спама ошибок. Часто применяется throttling или debounce на уровне обработки событий.


Логирование и диагностика геоошибок

Для стабильных картографических приложений критично собирать телеметрию:

  • код ошибки
  • браузер и версия
  • тип устройства
  • параметры запроса (timeout, accuracy)
  • время ответа

Пример структуры логов:

function logGeoError(error) {
  const payload = {
    code: error.code,
    message: error.message,
    timestamp: Date.now(),
    userAgent: navigator.userAgent
  };

  sendToServer('/geo-errors', payload);
}

Диагностика позволяет выявлять системные проблемы, например массовые TIMEOUT на определённых устройствах или регионах.


UX-стратегии при ошибках геолокации

Обработка ошибок не ограничивается техническим уровнем. В интерфейсной логике выделяются устойчивые состояния:

  • неопределённая позиция
  • ограниченный доступ
  • ручной режим выбора
  • режим последней известной позиции

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

Практика включает:

  • отображение кнопки повторного запроса
  • объяснение причины отказа через статус
  • автоматическое переключение на альтернативный источник координат

Особенности поведения в мобильных браузерах

Мобильные среды добавляют дополнительные факторы:

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

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


Безопасный контекст и ограничения HTTPS

Geolocation API доступен только в secure context. Это означает:

  • обязательное использование HTTPS
  • запрет на работу в file://
  • ограничения в embedded iframe без соответствующих permissions

Ошибка в этом случае не всегда явно кодируется через error.code, что требует дополнительной проверки:

if (!navigator.geolocation) {
  console.error('Geolocation API недоступен в этом контексте');
}

Согласование состояния карты с ошибками геолокации

В MapLibre-проектах важно синхронизировать визуальное состояние карты с состоянием геолокации:

  • отключение follow-mode при ошибке
  • сброс маркера пользователя
  • фиксация камеры в последней валидной позиции
  • предотвращение бесконечных flyTo при повторяющихся ошибках

Такая синхронизация предотвращает деградацию UX при нестабильных данных.