Mapbox GL JS построен вокруг событийно-асинхронной архитектуры, где почти все операции, связанные с картой, источниками данных и стилями, выполняются не синхронно, а через очередь загрузки и внутренние обработчики состояния. Это обусловлено тем, что отображение карты зависит от множества внешних ресурсов: тайлов, шрифтов, спрайтов, изображений, конфигураций стиля и данных источников.
Асинхронность в данной библиотеке не является вспомогательной особенностью, а формирует основу жизненного цикла карты.
Создание экземпляра карты не означает готовность к работе с графическими слоями и источниками данных. Конструктор выполняет только первичную настройку объекта и запуск процесса загрузки ресурсов.
Ключевой момент — событие загрузки стиля:
load — фиксирует момент, когда базовый стиль и
обязательные ресурсы загруженыidle — сигнализирует, что отсутствуют активные сетевые
запросы и рендеринг завершёнАсинхронная модель проявляется сразу: доступ к слоям и источникам до
наступления load приводит к непредсказуемому поведению,
поскольку внутренняя очередь операций ещё не синхронизирована с
состоянием карты.
Вся работа карты строится через события:
Наиболее важные события:
style.load — завершение загрузки стиляstyledata — частичное обновление структуры стиляsourcedata — поступление данных из источниковdataloading — начало загрузки данныхrender — каждый кадр рендерингаКаждое событие отражает состояние внутреннего асинхронного конвейера, где данные проходят несколько стадий: запрос → загрузка → парсинг → рендер.
Стиль карты представляет собой JSON-конфигурацию, содержащую слои, источники, спрайты и шрифты. Его загрузка включает несколько параллельных операций:
Каждый из этих элементов загружается независимо, что формирует множественные параллельные асинхронные потоки.
Особенность заключается в том, что стиль считается активным только после завершения критического подмножества этих операций, однако вспомогательные ресурсы могут догружаться позже.
Источники (sources) в Mapbox GL JS являются основным
механизмом получения геоданных. Каждый тип источника имеет собственную
модель асинхронности:
Векторные тайлы загружаются по мере необходимости при изменении:
Каждый тайл представляет собой отдельный HTTP-запрос, выполняемый лениво.
Растровые тайлы загружаются аналогично, но дополнительно могут кешироваться браузером и внутренним механизмом библиотеки.
GeoJSON может быть:
В случае URL выполняется fetch, после чего данные
проходят парсинг и индексацию.
Несмотря на событийную модель, часть API предоставляет Promise-интерфейсы.
Загрузка изображений:
map.loadImage(url, callback)Процесс полностью асинхронен:
Добавление изображения в стиль также может быть асинхронным, особенно при загрузке из внешних источников.
Методы addSource и addLayer формально
синхронны, но фактически включаются в очередь операций рендеринга.
Причины асинхронного поведения:
Внутренне операции откладываются до ближайшего безопасного цикла рендеринга.
Рендеринг карты основан на цикле requestAnimationFrame.
Это означает:
Асинхронность здесь проявляется как батчинг изменений: множество вызовов API не приводит к мгновенному перерисовыванию.
Спрайты и glyphs являются критическими визуальными ресурсами, но загружаются отдельно от основного стиля.
Асинхронные особенности:
Каждый источник данных проходит через несколько асинхронных стадий:
loading — инициирован запросloaded — данные полученыtile ready — тайлы декодированыrender-ready — данные доступны GPUСобытие sourcedata может срабатывать многократно для
одного источника, отражая потоковую природу загрузки.
При перемещении карты может возникать большое количество параллельных запросов тайлов. Для управления этим используются:
Асинхронная модель здесь не просто параллельная, а конкурентная: новые запросы могут вытеснять старые до их завершения.
Ошибки загрузки ресурсов обрабатываются через события:
error — общий обработчикТипичная особенность — отсутствие исключений в синхронном коде. Ошибки почти всегда проявляются позже, в асинхронных callback-цепочках.
Смена стиля является одной из наиболее сложных асинхронных операций:
В течение этого процесса карта может находиться в промежуточном состоянии, где часть данных ещё относится к старому стилю.
При добавлении пользовательских GeoJSON или внешних данных через fetch-цепочки возникает типичный поток:
fetchaddSourceКаждый этап зависит от завершения предыдущего, формируя цепочку промисов.
Значительная часть асинхронной нагрузки выносится в Web Workers:
Это позволяет не блокировать основной поток UI, но создаёт дополнительный уровень асинхронности между потоками.
При изменении камеры происходит перерасчёт:
Этот процесс полностью асинхронен и зависит от:
Система пытается предсказать потребности и заранее загружать тайлы, создавая эффект упреждающей асинхронной загрузки.
Событие idle является ключевым маркером
стабилизации:
Однако даже в этом состоянии новые асинхронные операции могут быть инициированы сразу после взаимодействия с картой, что возвращает систему в активный цикл.
Каждый кадр рендеринга проходит через последовательность:
Асинхронность здесь проявляется как непрерывный поток частично завершённых операций, распределённых между кадрами.