Как выполнить callback по завершению события на JavaScript

1. Когда может понадобится сделать callback функцию при завершении события на веб странице?

  1. Когда мы делаем ресайз браузера, а точнее видимой части страницы ("viewport") и мы хотим перестроить вёрстку по завершению ресайза, а не каждую миллисекунду данного ресайза...
  2. Когда мы что-то хотим сделать по завершении скролла, а не каждую миллисекунду скролла...
  3. Список можете продолжить самостоятельно, главная суть: что нам необходимо выполнить какое-то действие на JavaScript при окончании события...

2. Итак рассмотрим пример использования скрипта выполнения функции при завершении ресайза окна браузера (viewport) на JavaScript

  1. Если вы плохо разбираетесь как могут быть подключены вспомогательные функции к сайту, то есть статья Как можно подключить скрипт JavaScript к сайту?

  2. Функция передаётся как обработчик того или иного продолжительного события в браузере

  3. При первой загрузке скрипта выполняем нашу функцию напрямую

  4. Через 250 ms после окончания window resize выполнится callback moveSearchElemByResizeViewport, но не раньше!

  5. Функция isMinWidth здесь не предствалена, она проверяет через JavaScript, что текущая ширина является минимум переданному числу пикселей

  6. Функция moveElemTo здесь не предствалена, она перемещает элемент из обёртки в обёртку

document.addEventListener("DOMContentLoaded", function () {    
  try {    
      
      
      
    // 1. При первой загрузке скрипта выполняем нашу функцию напрямую
    moveSearchElemByResizeViewport();

    // 2. Через 250 ms после окончания window resize выполнится callback moveSearchElemByResizeViewport, но не раньше!
    window.addEventListener(
      "resize",
      onEventEndThenStartCallback(250, moveSearchElemByResizeViewport)
    );

    function moveSearchElemByResizeViewport() {
      // 3. Функция isMinWidth здесь не предствалена, она проверяет через JavaScript
      if (isMinWidth(576)) {
        // 4. Функция moveElemTo здесь не предствалена, она перемещает элемент из обёртки в обёртку
        moveElemTo({
          elem: ".search__wrapper",
          to: ".header__menu",
          where: "append",
        });
      } else {
        moveElemTo({
          elem: ".search__wrapper",
          to: ".header__panel",
          where: "append",
        });
      }
    }



  } catch (err) {
    console.error(err);
  } finally {
  }
});

Итого:

3. Какие есть параметры у функции выполнения callback по завершении и начале события

  1. Количество миллисекунд в течении которых при бездействии начатого события срабатывает callback
  2. Название функции (callback) которая сработает по окончании переданых миллисекунд бездействия начатого события
  3. Аргументы которые передаются в функцию завершения события, по умолчанию без аргументов
onEventEndThenStartCallback(  
  ms,  
  callbackByEventEnd,  
  optionsCallbackEnd = null,  
 )  

Сам код функции для выполнения callback по завершению события и при начале события на JavaScript

/**
 * @source https://stackoverflow.com/questions/45905160/javascript-on-window-resize-end#answer-45905199
 * @author Artem Kuznecov - artemsites.ru
 * @version 1.7 - 8.12.2023
 * @source https://gist.github.com/artemijeka/500e1d9071581d826d8e4b7380e63c2c
 * @param {Function} callbackByEventEnd - callback при окончании события | callback at the end of the event
 * @param {Object} objParamsCallbackEnd - объект аргумент для функции callbackByEventEnd | object argument for the callbackByEventEnd function
 * @param {Number}   ms - временной промежуток после окончания события чтобы выполнить callbackByEventEnd | the time interval after the end of the event to execute callbackByEventEnd
 * @param {Function} callbackByEventStart - callback при старте события | callback at the start of the event
 * @param {Object} objParamsCallbackStart - объект аргумент для функции callbackByEventStart | object argument for the callbackByEventStart function
 *
 * @example: window.addEventListener("resize", onEventEndThenStartCallback(250, showBtnMoreAndInitLogic, null, hideBtnMoreAndResetLogic, null));
 */
export function onEventEndThenStartCallback(
  ms,
  callbackByEventEnd,
  objParamsCallbackEnd = null,
  callbackByEventStart = null,
  objParamsCallbackStart = null
) {
  let timer;
  let eventStarted = false;

  return function (event) {
      if (callbackByEventStart && !eventStarted) {
          eventStarted = true;
          callbackByEventStart(objParamsCallbackStart);
      }

      if (timer) clearTimeout(timer);
      timer = setTimeout(
          function () {
              eventStarted = false;
              callbackByEventEnd(objParamsCallbackEnd);
          },
          ms,
          event
      );
  };
}