Fallback-решения представляют собой набор механизмов, обеспечивающих работоспособность картографического приложения при возникновении ограничений среды выполнения, сетевых проблем, отсутствия поддержки определённых технологий или ошибок загрузки ресурсов.
В веб-картографии устойчивость приложения играет критически важную роль. Пользователь может работать через медленное соединение, использовать устаревший браузер, находиться за корпоративным прокси-сервером или столкнуться с недоступностью внешних сервисов. Без заранее предусмотренных fallback-механизмов карта может полностью перестать отображаться.
Основные категории fallback-решений:
Перед проектированием fallback-механизмов необходимо понимать основные точки отказа.
Mapbox GL JS загружает стиль по URL:
style: 'mapbox://styles/mapbox/streets-v12'
Возможные проблемы:
Карта строится на основе множества тайлов.
Причины отказов:
Mapbox GL JS полностью зависит от WebGL.
Некоторые причины недоступности:
Динамические данные часто загружаются через API:
map.addSource('cities', {
type: 'geojson',
data: '/api/cities'
});
Если API недоступен, соответствующий слой не будет отображён.
Первым этапом обычно становится определение возможности запуска Mapbox GL JS.
Mapbox предоставляет специальный метод:
if (!mapboxgl.supported()) {
console.error('WebGL не поддерживается');
}
Более практичный вариант:
if (!mapboxgl.supported()) {
document.getElementById('map').innerHTML =
'<p>Карта недоступна в данном браузере.</p>';
}
При отсутствии WebGL может отображаться:
Пример:
if (!mapboxgl.supported()) {
const image = document.createElement('img');
image.src = '/static-map.png';
image.alt = 'Карта';
document.getElementById('map').appendChild(image);
}
Такой подход обеспечивает базовую доступность информации даже без интерактивной карты.
Mapbox GL JS генерирует событие ошибок.
map.on('error', (e) => {
console.error(e.error);
});
Пример расширенной обработки:
map.on('error', (e) => {
showNotification(
'Произошла ошибка загрузки карты'
);
sendErrorToMonitoring(e.error);
});
Преимущества:
Одним из наиболее распространённых fallback-подходов является автоматическая замена недоступного стиля.
const primaryStyle =
'mapbox://styles/company/main-style';
const fallbackStyle =
'mapbox://styles/mapbox/streets-v12';
Пример переключения:
const map = new mapboxgl.Map({
container: 'map',
style: primaryStyle
});
map.on('error', (e) => {
if (e.error) {
map.setStyle(fallbackStyle);
}
});
Особенно надёжным вариантом является размещение JSON-стиля на собственном сервере.
style: '/styles/fallback-style.json'
Преимущества:
GeoJSON часто загружается из API.
fetch('/api/objects')
fetch('/backup/objects.json')
Реализация:
async function loadData() {
try {
const response =
await fetch('/api/objects');
return await response.json();
} catch {
const response =
await fetch('/backup/objects.json');
return await response.json();
}
}
Данный механизм позволяет сохранять отображение объектов даже при отказе основного API.
Одним из лучших fallback-инструментов является Local Storage.
const data = await response.json();
localStorage.setItem(
'cachedData',
JSON.stringify(data)
);
const cached =
localStorage.getItem('cachedData');
if (cached) {
source.setData(
JSON.parse(cached)
);
}
try {
const response =
await fetch('/api/objects');
const data =
await response.json();
localStorage.setItem(
'cachedData',
JSON.stringify(data)
);
source.setData(data);
} catch {
const cached =
localStorage.getItem('cachedData');
if (cached) {
source.setData(
JSON.parse(cached)
);
}
}
Такой сценарий позволяет продолжать работу даже после потери соединения.
Для больших объёмов данных Local Storage становится недостаточным.
Преимущества IndexedDB:
Схема работы:
API
↓
IndexedDB
↓
Mapbox Source
Алгоритм:
Mapbox использует множество пользовательских иконок.
map.loadImage(
'/icons/shop.png',
callback
);
map.loadImage(
'/icons/shop.png',
(error, image) => {
if (error) {
map.loadImage(
'/icons/default.png',
fallbackHandler
);
return;
}
map.addImage('shop', image);
}
);
Подобный подход предотвращает исчезновение символов на карте.
Некоторые слои могут зависеть от внешних сервисов.
Например:
Weather API
Traffic API
Logistics API
При отказе сервиса слой может быть скрыт.
try {
await loadTrafficLayer();
} catch {
map.setLayoutProperty(
'traffic-layer',
'visibility',
'none'
);
}
Пользователь продолжит работу с остальной частью карты.
Полное отключение карты редко является лучшим решением.
Гораздо эффективнее отключать отдельные возможности.
Полная интерактивность:
Отключение тяжёлых компонентов:
map.removeLayer('buildings-3d');
Отключение анимаций:
map.jumpTo({
center: [30, 50],
zoom: 8
});
вместо
map.flyTo({
center: [30, 50],
zoom: 8
});
Статическая карта.
Подобная стратегия позволяет сохранить максимальную работоспособность.
Современные браузеры позволяют отслеживать состояние сети.
navigator.onLine
Пример:
window.addEventListener(
'offline',
() => {
showOfflineMessage();
}
);
window.addEventListener(
'online',
() => {
refreshMapData();
}
);
Многие сетевые ошибки являются временными.
async function fetchWithRetry(
url,
retries = 3
) {
for (
let i = 0;
i < retries;
i++
) {
try {
const response =
await fetch(url);
return response.json();
} catch {
await new Promise(
r => setTimeout(r, 1000)
);
}
}
throw new Error('Ошибка загрузки');
}
Данный механизм значительно повышает устойчивость приложения.
Иногда требуется возможность смены поставщика картографических данных.
Архитектура:
Mapbox
↓
Ошибка
↓
MapLibre
↓
Ошибка
↓
Статическая карта
Пример конфигурации:
const providers = [
mapboxStyle,
backupStyle,
localStyle
];
При ошибке используется следующий вариант.
Поиск адресов также является потенциальной точкой отказа.
Mapbox Geocoding API
Nominatim
Обёртка:
async function geocode(query) {
try {
return await mapboxGeocode(query);
} catch {
return await nominatimGeocode(query);
}
}
Это обеспечивает непрерывность поиска объектов.
Fallback-механизмы должны сопровождаться системой наблюдения.
Полезно отслеживать:
Пример:
map.on('error', (e) => {
analytics.track(
'map_error',
{
message: e.error.message
}
);
});
Накапливаемая статистика позволяет выявлять наиболее проблемные компоненты системы.
Практическая схема может выглядеть следующим образом:
Mapbox GL JS
│
├── Основной стиль
│ │
│ └── Fallback стиль
│
├── Основной API
│ │
│ └── Cached GeoJSON
│
├── Пользовательские иконки
│ │
│ └── Иконки по умолчанию
│
├── Онлайн режим
│ │
│ └── IndexedDB
│
└── WebGL
│
└── Статическая карта
Подобная многоуровневая система обеспечивает высокую устойчивость приложений на базе Mapbox GL JS к сетевым сбоям, отказам внешних сервисов, ошибкам конфигурации и ограничениям клиентской среды, сохраняя доступность картографической информации даже в неблагоприятных условиях эксплуатации.