Система событий в Google Maps JavaScript API построена вокруг
менеджера google.maps.event, который обеспечивает привязку
обработчиков к объектам карты, маркерам, оверлеям и DOM-событиям.
Архитектура ориентирована на явное управление жизненным циклом подписок,
поскольку объекты карты часто существуют длительное время и могут
динамически пересоздаваться.
Каждый вызов регистрации обработчика возвращает ссылку на слушатель, которая становится ключевым элементом для последующего удаления.
Базовый механизм подписки использует функции:
google.maps.event.addListenergoogle.maps.event.addDomListener (устаревший
подход)google.maps.event.addListenerOnceПример регистрации:
const map = new google.maps.Map(document.getElementById("map"), {
center: { lat: 40, lng: -70 },
zoom: 8,
});
const listener = google.maps.event.addListener(map, "click", (event) => {
console.log(event.latLng);
});
Возвращаемый объект listener содержит внутренние данные
о подписке, включая ссылку на источник события и функцию-обработчик.
Именно он используется для удаления.
Основной механизм удаления реализован через:
google.maps.event.removeListener(listener)google.maps.event.removeListener(listener);
Удаление происходит строго по ссылке, возвращённой при создании подписки. Попытка удалить обработчик без сохранённого идентификатора делает операцию невозможной.
Внутренне система событий освобождает привязку между объектом источника и callback-функцией, предотвращая дальнейшие вызовы обработчика.
Слушатель существует до тех пор, пока выполняются одновременно три условия:
map,
marker)addListenerOnce)Одноразовые слушатели автоматически удаляются после первого вызова:
google.maps.event.addListenerOnce(map, "idle", () => {
console.log("карта загружена");
});
Для полного освобождения всех привязок используется:
google.maps.event.clearInstanceListeners(object)google.maps.event.clearInstanceListeners(map);
Этот вызов удаляет все события, связанные с конкретным экземпляром (например, картой или маркером), включая пользовательские и системные обработчики.
Такой подход применяется при уничтожении UI-компонентов или при полной перезагрузке карты.
В API предусмотрена возможность очистки всех обработчиков конкретного события:
google.maps.event.clearListeners(instance, eventName)google.maps.event.clearListeners(map, "click");
Этот метод удаляет все callback-функции, привязанные к указанному событию, но не затрагивает остальные события объекта.
В сложных приложениях один объект может иметь десятки подписок. Типичный подход заключается в хранении всех ссылок:
const listeners = [];
listeners.push(
google.maps.event.addListener(map, "click", onClick),
google.maps.event.addListener(map, "zoom_changed", onZoom)
);
Удаление:
listeners.forEach((l) => google.maps.event.removeListener(l));
listeners.length = 0;
Такой паттерн снижает риск утечек памяти, особенно при динамическом создании и уничтожении компонентов.
Маркер является частым источником накопления слушателей:
const marker = new google.maps.Marker({
position: { lat: 50, lng: 30 },
map,
});
const clickListener = google.maps.event.addListener(marker, "click", () => {
console.log("marker clicked");
});
Удаление маркера не гарантирует автоматическую очистку всех внешних ссылок на обработчики, если они сохранены в переменных. Поэтому явное удаление:
google.maps.event.removeListener(clickListener);
marker.setMap(null);
При большом количестве маркеров применяется стратегия централизованного менеджмента подписок.
В контексте Google Maps JavaScript API утечки чаще всего возникают из-за:
listener, которые никогда не
удаляютсяОсобенно критичны ситуации, когда обработчик замыкает
map, marker и внешние состояния одновременно,
что удерживает объекты в памяти даже после удаления карты с DOM.
При полном уничтожении экземпляра карты применяется комбинированная стратегия:
listeners.forEach((l) => google.maps.event.removeListener(l));
google.maps.event.clearInstanceListeners(map);
map = null;
Такой подход разрывает все связи между системой событий и объектом карты.
В современных версиях Google Maps JavaScript API метод
removeListener остаётся основным способом удаления
одиночных подписок, тогда как более старые подходы через
clearListeners и clearInstanceListeners
используются для массовой очистки.
Важно учитывать, что DOM-ориентированные методы
(addDomListener) постепенно считаются устаревшими, и их
поведение в современных приложениях заменяется стандартными браузерными
addEventListener/removeEventListener.
Распространённые архитектурные подходы:
class MapEventManager {
constructor() {
this.listeners = [];
}
add(listener) {
this.listeners.push(listener);
return listener;
}
clear() {
this.listeners.forEach((l) => google.maps.event.removeListener(l));
this.listeners = [];
}
}
В приложениях с компонентной архитектурой слушатели привязываются к этапам:
removeListener и
clearInstanceListenersПри работе с динамическими слоями карты (например, фильтры маркеров или обновляемые данные) создаются временные подписки:
function attachTemporaryListener(map) {
const l = google.maps.event.addListener(map, "bounds_changed", () => {
console.log("bounds updated");
});
setTimeout(() => {
google.maps.event.removeListener(l);
}, 5000);
}
Подобные сценарии требуют строгого контроля времени жизни подписок, поскольку автоматическое удаление отсутствует.
| Метод | Назначение | Область действия |
|---|---|---|
removeListener |
удаление одного слушателя | конкретная подписка |
clearListeners |
очистка событий по типу | одно событие объекта |
clearInstanceListeners |
полная очистка объекта | все события объекта |
Если объект карты или маркера уничтожается без явной очистки слушателей, поведение зависит от сборщика мусора JavaScript. Однако наличие замыканий и сохранённых ссылок в обработчиках может препятствовать освобождению памяти.
Поэтому явное управление жизненным циклом слушателей остаётся обязательной частью архитектуры при работе с Google Maps JavaScript API.
Частый источник проблем:
const data = new Array(1000000).fill("x");
google.maps.event.addListener(map, "click", () => {
console.log(data.length);
});
Даже после удаления слушателя через removeListener, при
сохранении ссылки на callback в другом месте или при циклических
зависимостях объект data может оставаться в памяти.
Повторное удаление одного и того же listener:
google.maps.event.removeListener(listener);
google.maps.event.removeListener(listener);
Второй вызов является безопасным и не приводит к ошибкам, но не имеет эффекта, так как связь уже разорвана.
В крупных системах с использованием Google Maps API применяется централизованный event-layer, который:
Такой слой часто становится критическим элементом архитектуры, поскольку напрямую влияет на производительность и потребление памяти при длительной работе приложения с картами.