Задача состоит в том, чтобы написать декоратор debounce с моментальным вызовом и подсчётом количества вызовов javascript

Рейтинг: -1Ответов: 1Опубликовано: 05.05.2023

Нужно, чтобы:

1.Первый вызов происходил моментально, а следующий не раньше, чем через интервал времени, причём интервал должен задаваться в момент применения декоратора к функции.

  1. Усовершенствуйте декоратор так, чтобы в свойстве count декорированной функции хранилось количество её вызовов.

  2. Усовершенствуйте декоратор так, чтобы в свойстве allCount декорированной функции хранилось количество вызовов декоратора.

У меня считаются все вызовы функции и все вызовы декоратора.

Мой код:

function debounceDecoratorNew(func, delay) {

  let timeoutId;

  let count = 0;

  let allCount = 0;

  let hasCalled = false;

  function wrapper(...args) {

    if (timeoutId) {
      clearTimeout(timeoutId);
    }

    if (!wrapper.count) {
      wrapper.count = 0;
    }

    if (!wrapper.allCount) {
      wrapper.allCount = 0;
    }

    wrapper.count++;
    wrapper.allCount++;

    if (!hasCalled) {
      func.apply(this, args);
      hasCalled = true;
    } else {
      timeoutId = setTimeout(() => {
        func.apply(this, args);
        hasCalled = true;
      }, delay);
    }
  }

  wrapper.count = count;

  wrapper.allCount = allCount;

  return wrapper;

}

Есть проверки:

const sendSignal = (signalOrder, delay) => console.log("Сигнал отправлен", signalOrder, delay);

const upgradedSendSignal = debounceDecoratorNew(sendSignal, 2000);

setTimeout(() => upgradedSendSignal(1, 0)); // Сигнал отправлен + будет запланирован асинхронный запуск, который будет проигнорирован, так как следующий сигнал отменит предыдущий (300 - 0 < 2000)

setTimeout(() => upgradedSendSignal(2, 300), 300); // проигнорировано, так как следующий сигнал отменит предыдущий (900 - 300 < 2000)

setTimeout(() => upgradedSendSignal(3, 900), 900); // проигнорировано, так как следующий сигнал отменит предыдущий (1200 - 900 < 2000)

setTimeout(() => upgradedSendSignal(4, 1200), 1200); // проигнорировано, так как следующий сигнал отменит предыдущий (2300 - 1200 < 2000)

setTimeout(() => upgradedSendSignal(5, 2300), 2300); // Сигнал отправлен, так как следующий вызов не успеет отменить текущий: 4400-2300=2100 (2100 > 2000)

setTimeout(() => upgradedSendSignal(6, 4400), 4400); // проигнорировано, так как следующий сигнал отменит предыдущий (4500 - 4400 < 2000)

setTimeout(() => upgradedSendSignal(7, 4500), 4500); // Сигнал будет отправлен, так как последний вызов debounce декоратора (спустя 4500 + 2000 = 6500) 6,5с

setTimeout(() => {
  console.log(upgradedSendSignal.count); // было выполнено 3 отправки сигнала
  console.log(upgradedSendSignal.allCount); // было выполнено 6 вызовов декорированной функции
}, 7000)

Ответы

▲ 1Принят

Вы каждый раз при вызове функции увеличиваете счетчики двух ваших показателей.

Их необходимо увеличивать по событию

Вот пример функции

function debounceDecoratorNew(func, delay) {
  let timeoutId;
  let hasCalled = false;
  function doIt(args) { // Убираем дубликат кода
    func.apply(this, args);
    hasCalled = true;
    wrapper.count++; // Увеличиваем сигналы
  }

  function wrapper(...args) {
    if (timeoutId) clearTimeout(timeoutId);
    if (!wrapper.count) wrapper.count = 0;
    if (!wrapper.allCount) wrapper.allCount = 0;

    if (!hasCalled) {
      doIt(args);
    } else {
      wrapper.allCount++; // Увеличиваем вызовы
      timeoutId = setTimeout(() => doIt(args), delay);
    }
  }
  return wrapper;
}

Полный код с проверками

function debounceDecoratorNew(func, delay) {
  let timeoutId;
  let hasCalled = false;

  function doIt(args) {
    func.apply(this, args);
    hasCalled = true;
    wrapper.count++;
  }

  function wrapper(...args) {
    if (timeoutId) clearTimeout(timeoutId);
    if (!wrapper.count) wrapper.count = 0;
    if (!wrapper.allCount) wrapper.allCount = 0;

    if (!hasCalled) {
      doIt(args);
    } else {
      wrapper.allCount++;
      timeoutId = setTimeout(() => doIt(args), delay);
    }
  }
  return wrapper;
}

const sendSignal = (signalOrder, delay) => console.log("Сигнал отправлен", signalOrder, delay);

const upgradedSendSignal = debounceDecoratorNew(sendSignal, 2000);

setTimeout(() => upgradedSendSignal(1, 0)); // Сигнал отправлен + будет запланирован асинхронный запуск, который будет проигнорирован, так как следующий сигнал отменит предыдущий (300 - 0 < 2000)

setTimeout(() => upgradedSendSignal(2, 300), 300); // проигнорировано, так как следующий сигнал отменит предыдущий (900 - 300 < 2000)

setTimeout(() => upgradedSendSignal(3, 900), 900); // проигнорировано, так как следующий сигнал отменит предыдущий (1200 - 900 < 2000)

setTimeout(() => upgradedSendSignal(4, 1200), 1200); // проигнорировано, так как следующий сигнал отменит предыдущий (2300 - 1200 < 2000)

setTimeout(() => upgradedSendSignal(5, 2300), 2300); // Сигнал отправлен, так как следующий вызов не успеет отменить текущий: 4400-2300=2100 (2100 > 2000)

setTimeout(() => upgradedSendSignal(6, 4400), 4400); // проигнорировано, так как следующий сигнал отменит предыдущий (4500 - 4400 < 2000)

setTimeout(() => upgradedSendSignal(7, 4500), 4500); // Сигнал будет отправлен, так как последний вызов debounce декоратора (спустя 4500 + 2000 = 6500) 6,5с

setTimeout(() => {
  console.log('Сигналы:', upgradedSendSignal.count); // было выполнено 3 отправки сигнала
  console.log('Вызовы:', upgradedSendSignal.allCount); // было выполнено 6 вызовов декорированной функции
}, 7000)