Поломался 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 мс???


Ответы (0 шт):