Управление памятью

Библиотека iziToast создаёт DOM-элементы для каждого уведомления, добавляя их в контейнер на странице. При интенсивном использовании (частые уведомления, длительное время жизни страницы) важно контролировать жизненный цикл этих элементов, чтобы избежать утечек памяти и деградации производительности.

Каждое уведомление представляет собой объект с привязанными обработчиками событий, таймерами и ссылками на DOM. Если уведомление не удаляется корректно, связанные ресурсы остаются в памяти.


Жизненный цикл уведомления

Основные этапы:

  1. Создание — формирование DOM-узла и регистрация обработчиков
  2. Отображение — добавление в контейнер и запуск анимаций
  3. Активное состояние — работа таймера автозакрытия
  4. Удаление — очистка DOM и освобождение ресурсов

Ключевой момент управления памятью — корректное завершение последнего этапа.


Автоматическое удаление уведомлений

По умолчанию используется параметр timeout, который определяет время жизни уведомления:

iziToast.show({
    title: 'Уведомление',
    message: 'Автоматическое закрытие',
    timeout: 3000
});

После истечения времени:

  • удаляется DOM-элемент
  • очищаются таймеры
  • снимаются обработчики событий

Рекомендация: избегать бесконечных уведомлений (timeout: false) без явного механизма удаления.


Ручное управление удалением

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

iziToast.hide({}, document.querySelector('.iziToast'));

Или закрывать все:

iziToast.destroy();

Особенности:

  • hide() удаляет конкретный элемент
  • destroy() очищает контейнер и все связанные объекты

Использование destroy() особенно важно при:

  • переходах между страницами в SPA
  • повторной инициализации интерфейса

Работа с обработчиками событий

Каждое уведомление может содержать события:

iziToast.show({
    title: 'Событие',
    message: 'Клик',
    onClosing: function(instance, toast, closedBy){
        console.log('Закрывается');
    }
});

При неправильном использовании:

  • обработчики могут сохранять ссылки на внешние объекты
  • это препятствует сборке мусора

Практика:

  • не хранить глобальные ссылки внутри обработчиков
  • избегать замыканий на крупные структуры данных

Очистка таймеров

iziToast использует setTimeout для автозакрытия. При ручном удалении важно учитывать:

iziToast.hide({
    transitionOut: 'fadeOut'
}, toastElement);

Библиотека автоматически очищает таймеры, однако:

  • при модификации поведения (кастомные плагины)
  • при внешнем управлении DOM

необходимо убедиться, что таймеры не остаются активными.


Повторное использование контейнера

Контейнер уведомлений создаётся один раз и переиспользуется. Однако:

  • при множественных инициализациях (например, в SPA)
  • при динамической подгрузке модулей

возможно дублирование контейнеров.

Контроль:

if (document.querySelector('.iziToast-wrapper')) {
    iziToast.destroy();
}

Это предотвращает накопление неиспользуемых DOM-узлов.


Ограничение количества уведомлений

Большое количество одновременно активных уведомлений увеличивает нагрузку:

iziToast.settings({
    maxWidth: 350,
    timeout: 2000
});

Для контроля можно реализовать собственный лимит:

const MAX_TOASTS = 5;

if (document.querySelectorAll('.iziToast').length >= MAX_TOASTS) {
    iziToast.hide({}, document.querySelector('.iziToast'));
}

Преимущества:

  • снижение нагрузки на DOM
  • уменьшение количества активных обработчиков
  • более предсказуемое поведение интерфейса

Использование делегирования вместо прямых обработчиков

При большом количестве уведомлений предпочтительно:

  • избегать индивидуальных обработчиков для каждого элемента
  • использовать делегирование событий

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

  • важно минимизировать количество интерактивных элементов внутри уведомлений
  • избегать вложенных сложных компонентов

Утечки памяти в SPA-приложениях

Наиболее распространённые причины:

  • уведомления не удаляются при смене маршрута
  • ссылки на DOM остаются в состоянии приложения
  • повторная инициализация библиотеки

Подход:

window.addEventListener('beforeunload', () => {
    iziToast.destroy();
});

В SPA аналогично:

router.beforeEach((to, from, next) => {
    iziToast.destroy();
    next();
});

Работа с замыканиями

Пример потенциальной утечки:

let largeData = new Array(1000000);

iziToast.show({
    message: 'Данные',
    onClosing: function() {
        console.log(largeData);
    }
});

Проблема:

  • largeData остаётся в памяти до удаления уведомления

Решение:

  • не захватывать большие структуры
  • использовать минимальные данные

Очистка при удалении DOM вручную

Если уведомление удаляется не через API:

toastElement.remove();

возникают проблемы:

  • таймеры продолжают работать
  • обработчики не снимаются

Правильный способ:

  • использовать только API библиотеки

Диагностика утечек памяти

Инструменты браузера:

  • вкладка Performance
  • вкладка Memory (Heap Snapshot)

Признаки проблем:

  • рост количества DOM-узлов .iziToast
  • увеличение числа слушателей событий
  • отсутствие освобождения памяти после удаления

Оптимизация при высокой нагрузке

При частом создании уведомлений:

  • уменьшать timeout
  • отключать анимации:
iziToast.show({
    animateInside: false,
    transitionIn: 'fadeIn',
    transitionOut: 'fadeOut'
});
  • использовать очередь уведомлений
  • избегать массового создания в циклах

Кэширование и повторное использование данных

Вместо передачи больших объектов:

iziToast.show({
    message: JSON.stringify(largeObject)
});

предпочтительно:

  • передавать только необходимую информацию
  • использовать идентификаторы вместо данных

Потоковое создание уведомлений

При генерации уведомлений из событий (например, WebSocket):

  • необходимо ограничивать частоту
  • использовать debounce/throttle
let lastToastTime = 0;

function safeToast() {
    const now = Date.now();
    if (now - lastToastTime > 1000) {
        iziToast.show({ message: 'Событие' });
        lastToastTime = now;
    }
}

Контроль за состоянием библиотеки

iziToast хранит внутреннее состояние (экземпляры, контейнеры). При неправильной работе:

  • состояние может рассинхронизироваться с DOM
  • появляются “висячие” элементы

Регулярная очистка:

iziToast.destroy();

и повторная инициализация помогают избежать накопления ошибок.


Минимизация нагрузки на сборщик мусора

Основные принципы:

  • короткое время жизни объектов
  • отсутствие лишних ссылок
  • своевременное удаление DOM

Это особенно важно в интерфейсах с:

  • живыми обновлениями
  • большим количеством событий
  • длительным временем работы страницы

Практика безопасного использования

  • всегда задавать timeout
  • использовать destroy() при смене контекста
  • избегать хранения ссылок на уведомления
  • не модифицировать DOM уведомлений напрямую
  • минимизировать обработчики и замыкания

Систематическое соблюдение этих правил обеспечивает стабильную работу интерфейса без накопления памяти и деградации производительности.