Обработка ошибок

Модель ошибок в Mapbox GL JS построена на сочетании событийной системы, внутренних WebGL-ошибок и сетевых сбоев при загрузке ресурсов стиля (тайлы, спрайты, шрифты, GeoJSON). Большая часть проблем проявляется не как исключения JavaScript, а как асинхронные события состояния карты, требующие подписки через map.on(...).


Основной механизм фиксации проблем — событие error. Оно срабатывает при ошибках загрузки ресурсов, некорректных стилях, проблемах тайлового сервера, токенах доступа и внутренних сбоях рендера.

map.on('error', (e) => {
    console.log('Mapbox error:', e.error);
});

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

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


Ошибки загрузки стиля и ресурсов

При инициализации карты загружается style JSON, который содержит ссылки на источники данных:

  • vector tiles
  • raster tiles
  • sprites
  • glyphs (шрифты)
  • images

Ошибка на любом этапе вызывает error, но причина часто скрыта в глубине цепочки загрузки.

Проблемы с style JSON

Типичные сценарии:

  • неверный URL стиля
  • отсутствие доступа (401 / 403)
  • повреждённый JSON
  • несовместимая версия спецификации
map.on('error', (e) => {
    if (e.error && e.error.status === 401) {
        console.log('Ошибка авторизации токена');
    }
});

Ошибки источников данных (sources)

Источники данных являются ядром визуализации. Ошибки в source проявляются при добавлении через addSource или во время загрузки тайлов.

Типовые проблемы:

  • неверный tiles URL
  • недоступный TileJSON
  • неправильный формат GeoJSON
  • превышение лимита запросов
map.on('error', (e) => {
    if (e.error && e.error.message.includes('source')) {
        console.log('Ошибка источника данных');
    }
});

GeoJSON ошибки

При использовании geojson источников часто возникают:

  • некорректная геометрия
  • отсутствующие координаты
  • нарушение RFC 7946

Mapbox GL JS может молча игнорировать часть данных, поэтому диагностика требует логирования исходных объектов до передачи в addSource.


Ошибки слоёв (layers)

Ошибки слоёв обычно связаны с:

  • ссылками на несуществующий source
  • неверным source-layer в vector tiles
  • ошибками фильтров
  • конфликтами типов слоёв
map.addLayer({
    id: 'cities',
    type: 'circle',
    source: 'cities-source',
    'source-layer': 'urban'
});

Если cities-source отсутствует, ошибка появится только во время рендеринга.

Особенность: Mapbox GL JS не всегда явно сообщает о проблеме слоя в виде исключения — часто ошибка проявляется через error событие без явного указания слоя.


Отсутствующие изображения и styleimagemissing

Отдельный класс ошибок связан с изображениями, используемыми в символах (symbol layers).

Если изображение не добавлено через addImage, срабатывает событие:

map.on('styleimagemissing', (e) => {
    console.log('Missing image:', e.id);
});

Это критически важно при динамических стилях, где иконки подгружаются асинхронно.

Типовой паттерн исправления:

map.on('styleimagemissing', (e) => {
    map.loadImage('/icons/' + e.id + '.png', (err, image) => {
        if (err) return;

        if (!map.hasImage(e.id)) {
            map.addImage(e.id, image);
        }
    });
});

Потеря WebGL контекста

WebGL контекст может быть потерян из-за:

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

Mapbox GL JS предоставляет события:

map.on('webglcontextlost', () => {
    console.warn('WebGL context lost');
});

map.on('webglcontextrestored', () => {
    console.log('WebGL context restored');
});

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


Сетевые ошибки и стратегии повторных попыток

Загрузка тайлов и ресурсов выполняется асинхронно через fetch-подобный механизм внутри Mapbox GL JS.

Типичные ошибки:

  • ECONNRESET
  • timeout
  • DNS failure
  • 429 rate limit
  • 5xx ошибки сервера

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

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

map.on('error', (e) => {
    const err = e.error;

    if (!err) return;

    if (err.status === 429) {
        console.log('Превышен лимит запросов');
    }

    if (err.message && err.message.includes('Network')) {
        console.log('Сетевая ошибка');
    }
});

Повторные попытки на уровне приложения

Mapbox GL JS не предоставляет полноценного retry механизма для всех ресурсов, поэтому часто используется внешний слой:

  • прокси CDN
  • локальное кеширование
  • повторная установка источника
function reloadSource(map, sourceId, data) {
    if (map.getSource(sourceId)) {
        map.removeSource(sourceId);
    }

    map.addSource(sourceId, {
        type: 'geojson',
        data
    });
}

Ошибки load и состояние карты

Инициализация карты сопровождается событием load, которое сигнализирует о завершении загрузки стиля.

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

  • load — стиль загружен
  • idle — рендеринг завершён
  • error — асинхронный сбой ресурсов
map.on('load', () => {
    console.log('Стиль загружен');
});

map.on('idle', () => {
    console.log('Карта стабилизировалась');
});

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


Защита от runtime-исключений

Хотя Mapbox GL JS редко бросает синхронные исключения, ошибки API (например, неправильные параметры addLayer) могут привести к throw.

Типичные источники исключений:

  • обращение к несуществующей карте (map ещё не инициализирован)
  • вызов addLayer до load
  • неправильная структура style specification
map.on('load', () => {
    try {
        map.addLayer({
            id: 'points',
            type: 'circle',
            source: 'points'
        });
    } catch (e) {
        console.error('Ошибка добавления слоя', e);
    }
});

Диагностика через логирование состояния стиля

Mapbox GL JS предоставляет доступ к текущему стилю:

const style = map.getStyle();
console.log(style.layers);
console.log(style.sources);

Это позволяет локализовать проблему:

  • отсутствующие источники
  • конфликтующие слои
  • некорректные ссылки

Ошибки фильтров и выражений

Expression API является частым источником скрытых проблем. Ошибки возникают при:

  • неверных типах данных
  • несовместимых операциях
  • обращении к несуществующим полям
map.addLayer({
    id: 'population',
    type: 'circle',
    source: 'cities',
    paint: {
        'circle-radius': ['get', 'population']
    }
});

Если population отсутствует или имеет строковый тип, поведение может быть непредсказуемым без явного error.


Паттерн централизованного обработчика ошибок

При сложных приложениях используется единая точка обработки:

function attachErrorHandler(map) {
    map.on('error', (e) => {
        const err = e.error;

        if (!err) return;

        const message = err.message || '';

        if (message.includes('sprite')) {
            console.log('Ошибка спрайта');
        } else if (message.includes('Tile')) {
            console.log('Ошибка тайлов');
        } else {
            console.log('Общая ошибка Mapbox:', err);
        }
    });
}

Контроль деградации отображения

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

  • отсутствующие тайлы → пустые области
  • ошибки шрифтов → пропавшие подписи
  • ошибки спрайтов → серые маркеры

Для таких случаев применяется наблюдение за визуальным состоянием через idle и периодическую проверку queryRenderedFeatures:

const features = map.queryRenderedFeatures();
console.log(features.length);

Особенности обработки ошибок в worker-архитектуре

Mapbox GL JS использует Web Workers для обработки тайлов и стиля. Это означает:

  • часть ошибок происходит вне main thread
  • stack trace может быть неполным
  • сообщения приходят агрегированно через error

Поэтому диагностика часто опирается не на стек вызовов, а на контекст события и тип ресурса.


Итоговая модель поведения при ошибках

  • ошибки асинхронны и событийны
  • критические сбои редки и связаны с WebGL или стилем
  • большинство проблем — сетевые и ресурсные
  • обработка строится через error, styleimagemissing, webglcontextlost
  • восстановление требует повторной инициализации источников и изображений
  • логирование состояния карты важнее перехвата исключений