Намаляване на отскока и дроселиране са техники, използвани за ограничаване на броя извиквания на функция за даден период от време. Те често се използват в ситуации, в които дадена функция се извиква няколко пъти в бърза последователност, като например когато потребител въвежда в поле за въвеждане или превърта на страница.

В друго определение:

Намаляване на отскока и дроселиране са техники, използвани заограничаване на броя извиквания на функция за определен период от време. Те са полезни за подобряване на производителността на приложение и предотвратяване на спирането му.

Ето пример за отстраняване на отскок в JavaScript:

function debounce(fn, delay) {
  let timeoutId;
  return function() {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => {
      fn.apply(this, arguments);
    }, delay);
  };
}

const debouncedFunction = debounce(() => {
  console.log("Function called!");
}, 1000);

// The function will only be called once, even if it's invoked multiple times within a 1 second period.

Обяснение:

Тук имаме функция debounce, която приема два аргумента, първият един е функцията, която трябва да бъде debounce и second е закъснението във времето. Вътре във функцията debounce имаме timeoutId и анонимна функция, която отнема без аргументи.

Първият ред в тази функция е да изчистите времето за изчакване с помощта на функцията clearTimeout и подаване на timeoutId като аргумент. След това задаваме времето за изчакване, като използваме функцията setTimeout с закъснение като втори аргумент, тази функция е обвита в анонимна функция, която извиква оригиналната функция предадено на функцията debounce с нейните аргументи.

Сега можем да използваме тази дебоункционирана функция, в предоставения пример тя регистрира „Извикана функция!“ към конзолата само веднъж, дори ако е извикан многократно в рамките на период от 1 секунда.

Ето пример за регулиране в JavaScript:

function throttle(fn, limit) {
  let inThrottle = false;
  return function() {
    if (!inThrottle) {
      fn.apply(this, arguments);
      inThrottle = true;
      setTimeout(() => inThrottle = false, limit);
    }
  };
}

const throttledFunction = throttle(() => {
  console.log("Function called!");
}, 1000);

// The function will be called once per second, even if it's invoked multiple times within that period.

Обяснение:

Тук имаме функция дросел, която приема два аргумента, първият един е функцията, която трябва да бъде дроселирана и второто е ограничението на времето. Вътре във функцията за газта имаме променлива inThrottle, която първоначално е зададена на false, тази променлива се използва за проверете дали функцията вече е извикана в рамките на предоставения лимит. След това имаме анонимна функция, която не приема аргументи.

Първият ред в тази функция е да се провери дали inThrottle е false, ако е true извиква оригиналната функция предава на дроселираща функция с нейните аргументи и задава inThrottle на true. След това задава изтичане на лимитираното време, след което задава inThrottle на false.

Сега можем да използваме тази ограничена функция, в предоставения пример тя регистрира „Извикана функция!“ към конзолата веднъж в секунда, дори ако е извикан многократно в рамките на този период.

Да вземем друг пример:

function debounce(func, wait) {
  let timeout;
  return function() {
    const context = this, args = arguments;
    clearTimeout(timeout);
    timeout = setTimeout(() => func.apply(context, args), wait);
  };
}

Функцията debounce приема два аргумента: функцията, която ще бъде извикана, и времето за изчакване в милисекунди. Вътре във функцията създаваме променлива за изчакване и връщаме нова функция. Тази нова функция ще изчисти всяко съществуващо изчакване и ще зададе ново изчакване с предоставената функция и време за изчакване.

Ето пример как да използвате функцията за премахване на отскок:

const debouncedFunction = debounce(() => {
  console.log('Debounced function called.');
}, 1000);

document.querySelector('#some-button').addEventListener('click', debouncedFunction);

В този пример създаваме дебоунжирана версия на анонимна функция, която записва съобщение в конзолата. След това го прикрепяме към събитие с щракване на бутон. Сега, когато върху бутона се щракне многократно в рамките на времето за изчакване от една секунда, функцията ще бъде извикана само веднъж, след като изтече времето за изчакване от последното щракване.

Ето пример за дроселираща функция в JavaScript:

function throttle(func, limit) {
  let lastFunc;
  let lastRan;
  return function() {
    const context = this;
    const args = arguments;
    if (!lastRan) {
      func.apply(context, args);
      lastRan = Date.now();
    } else {
      clearTimeout(lastFunc);
      lastFunc = setTimeout(function() {
        if ((Date.now() - lastRan) >= limit) {
          func.apply(context, args);
          lastRan = Date.now();
        }
      }, limit - (Date.now() - lastRan));
    }
  }
}

Дроселната функция приема два аргумента: функцията, която трябва да бъде извикана, и ограничението в милисекунди. Вътре във функцията създаваме променливи lastFunc и lastRan и връщаме нова функция. Тази нова функция ще провери дали последното извикване нафункцията е по-голямо от ограниченото време и ако е вярно, ще извика функцията, в противен случай ще изчака да изтече оставащото време.

Ето пример как да използвате функцията за газ:

const throttledFunction = throttle(() => {
  console.log('Throttled function called.');
}, 1000);

document.querySelector('#some-button').addEventListener('mousemove', throttledFunction);

В този пример създаваме ограничена версия на анонимна функция, която записва съобщение в конзолата. След това го прикрепяме към събитието mousemove на бутон. Сега, когато бутонът се задържи няколко пъти в рамките на ограничението от една секунда, функцията ще се извиква само веднъж в секунда.

Струва си да се отбележи, че горните примери за функции за намаляване на рикошетите и за дроселиране са само един от начините за прилагането им и има множество начини за прилагането им с различни вариации и компромиси.

#javascript #throttle #debounce #webperformance #frontendinterview