JQuery: отложенный вызов функции после окончания ресайза

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Для того чтобы событие resize начинало выполняться лишь после окончания изменения размеров окна, применяйте демпфер (debouncer), основанный на функции setTimeout:

JS
Скопировать код
let resizeTimer;
$(window).resize(function() {
    clearTimeout(resizeTimer);
    resizeTimer = setTimeout(() => {
        // Ваш код будет выполнен только после того, как изменение размеров окончено
        console.log('Изменение размеров окна завершено!');
    }, 250); // Задержка составляет 250 миллисекунд
});

В данном коде используется задержка, создаваемая при помощи функции setTimeout. Она каждый раз сбрасывается при новом событии resize. Выполнение команды clearTimeout гарантирует выполнение функции только один раз, и это произойдет после последнего события изменения размера. Задержку (в данном случае она равна 250 мс) можно настроить в соответствии с требованиями вашего проекта.

Кинга Идем в IT: пошаговый план для смены профессии

Освоение принципа работы демпфирования

Демпфирование (Debouncing) позволяет эффективно регулировать частоту возникновения событий. Если события начинают происходить слишком быстро и часто, это снижает производительность. Демпфирование обеспечивает начало работы события лишь после того, как проходит определенный промежуток времени бездействия.

Настройка времени демпфирования

Вам, как и акробату на канате, потребуется найти баланс между быстрой реакцией на события и оптимальной производительностью, настроив время демпфирования. Если задержка в 250 мс кажется вам слишком длинной, сократите ее. Если события изменения размеров возникают слишком часто, увеличьте время задержки. Настройте его исходя из специфики вашего приложения.

Исключаем незначительные события

Следует использовать некоторые подходы для отсеивания незначительных изменений размера окна, например, тех, которые происходят при появлении полос прокрутки:

  1. Отключите полосы прокрутки, меняя свойство overflow элемента body во время изменения размера окна.
  2. Запоминайте и сравнивайте размеры окна перед выполнением кода, чтобы удостовериться, что изменения действительно произошли.
JS
Скопировать код
let lastWidth = $(window).width(), lastHeight = $(window).height();
$(window).resize(function() {
    let newWidth = $(window).width(), newHeight = $(window).height();
    if(newWidth !== lastWidth || newHeight !== lastHeight){
        lastWidth = newWidth;
        lastHeight = newHeight;
        // Здесь выполняйте необходимые действия
    }
});

Визуализация

Можно представить демпфер как пост на шоссе:

Markdown
Скопировать код
На шоссе (🛣️) расположен пост (🚧), который пропускает транспорт через себя с определенной периодичностью:

| Действие             | Транспортное движение | Изменение размеров окна |
| -------------------- | --------------------- | ---------------------- |
| Непрерывное движение | 🚗🚕🚗🚕🚗🚕🚗🚕🚗       | Изменение размеров     |
| Работа поста         | 🚧 ... ... 🚧 ОТКРЫТО! | Сработал демпфер       |
| Один проезд          | 🚗 (Проезд разрешен)   | Событие запущено       |

Подобно посту, демпфер позволяет событию начать работу только после того, как прекращаются изменения размеров.

Хранение идентификатора таймаута изменения размеров

Чтобы не нарушать глобальный контекст, для надежного хранения идентификаторов таймеров используйте jQuery.data():

JS
Скопировать код
$(window).resize(function() {
    let timeoutId = $.data(this, 'resizeTimer');
    clearTimeout(timeoutId);

    timeoutId = setTimeout(() => {
        // Выполните нужные действия здесь
    }, 300);
    $.data(this, 'resizeTimer', timeoutId);
});

Используйте плагины или вспомогательные функции

Если вы предпочитаете не углубляться в детали реализации демпфирования, воспользуйтесь готовыми решениями, предлагаемыми плагинами для jQuery, например, jQuery Throttle/Debounce от Бена Алмана, или функциями из библиотек Underscore.js и Lodash:

JS
Скопировать код
$(window).resize(_.debounce(function() {
    // Вставьте сюда ваш код
}, 250));

Полезные материалы

  1. resize event | jQuery API Documentation
  2. Underscore.js
  3. Что такое функция "debounce" в JavaScript? – Stack Overflow
  4. Debouncing и Throttling обозначены через примеры | CSS-Tricks
  5. Window: resize event – Web APIs | MDN
  6. Документация Lodash
  7. GitHub – lodash/lodash: Современная утилитарная библиотека Javascript