Пользовательская функция debounce не работает с анонимными функциями - PullRequest
0 голосов
/ 21 ноября 2018

Я пытаюсь создать пользовательскую функцию отладки:

const debounced = [];

const cancelFunc = timeout => () => {
  clearTimeout(timeout);
};

function debounce(fn, wait, ...args) {  
  let d = debounced.find(({ func }) => func === fn);

  if (d) {
    d.cancel();  
  } else {
    d = {};
    debounced.push(d);
  }

  d.func = fn;   
  d.timeout = setTimeout(fn, wait, ...args);
  d.cancel = cancelFunc(d.timeout);
}

Если я использую с именованной функцией, она работает как задумано:

debounce(foo, 1000); // called once with 5 clicks in 1 second

Но я не могузаставить его работать с анонимными функциями:

debounce(() => { foo(5); }, 1000); // called 5 times with 5 clicks in 1 second

Я создал перо здесь: https://codepen.io/anon/pen/gQvMdR?editors=1011

Ответы [ 2 ]

0 голосов
/ 21 ноября 2018

Это происходит из-за вашего find состояния.Давайте вернемся назад и рассмотрим этот фрагмент кода:

if (
    (function(){ return 1 }) === (function(){ return 1 })
) {
    console.log('The functions are equal');
} else {
    console.log('The functions are NOT equal');
}

// logs 'The functions are NOT equal'

Несмотря на то, что я написал две идентичные анонимные функции, они не строго равны друг другу.Когда вы передаете эту анонимную функцию, это, по сути, то, что вы делаете.Таким образом, при поиске в вашем массиве ранее найденной функции он никогда не найдет совпадения, потому что каждый раз, когда debounce(() => { foo(5); }, 1000); вызывается, создает новую функцию .Поскольку совпадение никогда не будет найдено, оно никогда не будет отменено.

0 голосов
/ 21 ноября 2018

Как упомянуто @SLaks "Каждый вызов создает отдельную функцию, поэтому вы не найдете ее в массиве."

Так что вам просто нужно что-то сохранить в массивечтобы соответствовать ему, вы можете использовать .toString()

// ================

const debounced = [];

const cancelFunc = timeout => () => {
  clearTimeout(timeout);
};

function debounce(fn, wait, ...args) {
  let d = debounced.find(({ funcString }) => funcString === fn.toString());

  if (d) {
    d.cancel();
  } else {
    d = {};
    debounced.push(d);
  }

  d.func = fn;
  d.funcString = fn.toString()
  d.timeout = setTimeout(fn, wait, ...args);
  d.cancel = cancelFunc(d.timeout);
}

// ================

function foo(value) {
	console.log('value:', value)
}

function onClickBroken() {
  debounce(() => { foo(5); }, 1000);
}
<button onClick="onClickBroken()">Click me 5 times</button>
...