Реализуйте функцию `debounce`, которая поддерживает немедленный вызов в начале серии событий (`leading`), trailing-вызов в конце серии по умолчанию и метод `debounceFunc.cancel()` для отмены запланированного вызова.

Debounce перезапускает таймер на каждом вызове; leading выполняет первый вызов сразу, trailing — последний после паузы.

Короткий ответ

Что ответить на собеседовании

Debounce перезапускает таймер на каждом вызове; leading выполняет первый вызов сразу, trailing — последний после паузы.

Подробный разбор

Ответ с пояснениями

Debounce перезапускает таймер на каждом вызове; leading выполняет первый вызов сразу, trailing — последний после паузы.

Здесь при leading и trailing одиночный вызов не повторяется в конце; повторные вызовы используют последние аргументы и this:

function debounce(fn, wait, { leading = false, trailing = true } = {}) {
  if (typeof fn !== 'function' || !Number.isFinite(wait) || wait < 0) {
    throw new TypeError('Invalid debounce arguments');
  }
  let timer = null, args, context;
  function invoke() {
    const a = args, c = context;
    args = context = undefined;
    return fn.apply(c, a);
  }
  function wrapped(...nextArgs) {
    const first = timer === null;
    args = nextArgs;
    context = this;
    clearTimeout(timer);
    timer = setTimeout(() => {
      timer = null;
      if (trailing && args) invoke();
      else args = context = undefined;
    }, wait);
    if (first && leading) return invoke();
  }
  wrapped.cancel = () => {
    clearTimeout(timer);
    timer = null;
    args = context = undefined;
  };
  return wrapped;
}

Отмена убирает только ожидающий вызов и не отменяет уже выполняющуюся работу. Возврат Promise и maxWait этим контрактом не предусмотрены.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее