Работа с Google Maps JavaScript API предполагает постоянное взаимодействие с удалёнными серверами: загрузка скрипта API, тайлов карты, геокодирование, маршрутизация и поиск мест выполняются через сеть. Поэтому первым уровнем устойчивости становится определение состояния подключения браузера.
Используются встроенные механизмы браузера:
const isOnline = navigator.onLine;
и события изменения состояния сети:
window.addEventListener('online', () => {
console.log('Соединение восстановлено');
});
window.addEventListener('offline', () => {
console.log('Интернет отсутствует');
});
Эти события не гарантируют точного состояния соединения с интернетом (например, Wi-Fi может быть подключён без доступа к сети), однако они дают базовый сигнал для переключения режима работы интерфейса.
Google Maps JavaScript API подключается через
<script>-тег, и его загрузка может завершиться
неудачей при отсутствии сети или блокировке запросов.
Критически важно обрабатывать onerror:
<script
src="https://maps.googleapis.com/maps/api/js?key=API_KEY&callback=initMap"
async
defer
oner ror="handleMapLoadError()">
</script>
function handleMapLoadError() {
console.error('Не удалось загрузить Google Maps API');
showFallbackUI({
title: 'Карта недоступна',
message: 'Отсутствует подключение к интернету или сервер API недоступен'
});
}
При такой ошибке объект google.maps не будет определён,
поэтому любые обращения к нему должны выполняться только после
проверки:
if (!window.google || !window.google.maps) {
// запрет работы с картой
}
Инициализация карты должна учитывать возможное отсутствие сетевых ресурсов уже на этапе создания объекта:
let map;
function initMap() {
if (!navigator.onLine) {
renderOfflineState();
return;
}
map = new google.maps.Map(document.getElementById("map"), {
center: { lat: 51.1694, lng: 71.4491 },
zoom: 10
});
}
Если соединение пропадает после инициализации, карта продолжает отображаться, но новые тайлы и данные перестают загружаться.
Google Maps JavaScript API не выбрасывает явную ошибку при обрыве сети после загрузки. Вместо этого наблюдаются следующие эффекты:
Обработка таких ситуаций выполняется через проверку статусов ответов сервисов API:
const geocoder = new google.maps.Geocoder();
geocoder.geocode({ address: "Astana" }, (results, status) => {
if (status === "OK") {
console.log(results);
} else {
console.error("Ошибка геокодирования:", status);
}
});
Типичные статусы при проблемах с сетью:
UNKNOWN_ERRORREQUEST_DENIEDOVER_QUERY_LIMITZERO_RESULTS (не всегда связано с сетью)Интерфейс должен разделять три состояния:
Пример переключения состояния:
function updateConnectionState() {
if (!navigator.onLine) {
setUIState('offline');
} else if (!window.google?.maps) {
setUIState('api-unavailable');
} else {
setUIState('online');
}
}
Запросы к сервисам (геокодирование, маршруты, Places API) можно ставить в очередь при отсутствии сети.
const requestQueue = [];
function enqueueRequest(fn) {
requestQueue.push(fn);
}
window.addEventListener('online', () => {
while (requestQueue.length) {
const req = requestQueue.shift();
req();
}
});
Пример использования:
function safeGeocode(address) {
if (!navigator.onLine) {
enqueueRequest(() => safeGeocode(address));
return;
}
geocoder.geocode({ address }, callback);
}
Такой подход предотвращает потерю пользовательских действий в офлайн-сценариях.
Service Worker позволяет частично компенсировать отсутствие сети за счёт кэширования статических ресурсов приложения.
Базовая регистрация:
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js');
}
Внутри sw.js можно кэшировать собственные ресурсы
интерфейса:
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open('app-cache').then((cache) => {
return cache.addAll([
'/',
'/index.html',
'/styles.css',
'/app.js'
]);
})
);
});
Важно учитывать ограничение: динамические ресурсы Google Maps (тайлы карты, данные Places, маршруты) не предназначены для полноценного офлайн-кэширования через Service Worker в большинстве сценариев использования API и могут иметь ограничения со стороны платформы и условий сервиса.
При отсутствии сети интерфейс может переключаться на альтернативное представление:
Пример переключения контейнера:
function renderOfflineState() {
const mapContainer = document.getElementById("map");
mapContainer.innerHTML = `
<div class="offline-map">
<p>Карта недоступна</p>
</div>
`;
}
При частичной потере соединения тайлы могут не загружаться, оставляя серые блоки. Контроль таких ситуаций выполняется косвенно через события и наблюдение за состоянием DOM.
Дополнительно можно отслеживать ошибки API через глобальный обработчик:
window.gm_authFailure = function () {
console.error("Ошибка авторизации Google Maps API");
};
Для устойчивости к нестабильной сети используется стратегия повторных попыток:
async function retry(fn, attempts = 5, delay = 1000) {
for (let i = 0; i < attempts; i++) {
try {
return await fn();
} catch (e) {
await new Promise(r => setTimeout(r, delay * 2 ** i));
}
}
throw new Error("Все попытки завершились неудачей");
}
Этот подход особенно полезен для геокодирования и запросов маршрутов.
Дополнительно используется Network Information API:
const connection = navigator.connection;
if (connection) {
console.log(connection.effectiveType);
}
Значения:
slow-2g2g3g4gЭто позволяет заранее снижать частоту запросов и отключать тяжёлые функции.
При отсутствии интернета система должна различать:
Критические зависимости:
Некритические функции:
Такая сегментация позволяет сохранить работоспособность интерфейса даже при полной деградации сети.
В некоторых сценариях полезно сохранять состояние карты:
function saveMapState(map) {
const center = map.getCenter();
const zoom = map.getZoom();
localStorage.setItem('mapState', JSON.stringify({
lat: center.lat(),
lng: center.lng(),
zoom
}));
}
При восстановлении соединения это состояние используется для возврата пользователя к последнему просмотру.
Запросы к сервисам маршрутизации требуют отдельной обработки:
directionsService.route(request, (result, status) => {
if (status === "OK") {
directionsRenderer.setDirections(result);
} else {
console.error("Ошибка маршрута:", status);
showOfflineRouteHint();
}
});
При отсутствии сети такие запросы чаще всего возвращают
UNKNOWN_ERROR, что требует унифицированной обработки без
привязки к конкретному сервису.
Полноценная офлайн-работа невозможна из-за архитектуры API:
Поэтому офлайн-стратегии сводятся к: