Поломался setTimeout в функции-декораторе!
Имеем два совершенно идентичных кода простейшего декоратора. Единственное отличие: в одном вызов f до таймаута, в другом - после. 1-ый вариант:
let f = debounce(alert, 1000);
function debounce(f, ms) {
let isCooldown = false;
return function(...args) {
if (isCooldown) { return; }
isCooldown = true;
f.apply(this, args);
setTimeout(() => isCooldown = false, ms);
}
}
f(1); // выполняется немедленно
f(2); // проигнорирован
setTimeout( () => f(3), 100); // проигнорирован (прошло только 100 мс)
setTimeout( () => f(4), 1100); // выполняется
setTimeout( () => f(5), 1500); // проигнорирован (прошло только 400 мс от последнего вызова)
Всё работает отлично. НО стоит нам изменить один единственный порядок и сделать так:
isCooldown = true;
setTimeout(() => isCooldown = false, ms);
f.apply(this, args);
То по итогу выводится не 1 и 4, а 1, 3 и 5 (!!!) Почему так происходит? Да, на вызов функции тратится некоторое время, но таймаут ставится на целую секунду. Каким образом f(3) не игнорируется, будучи вызванной спустя всего лишь 100 мс???