Debounce перезапускает таймер на каждом вызове; leading выполняет первый вызов сразу, trailing — последний после паузы.
Реализуйте функцию `debounce`, которая поддерживает немедленный вызов в начале серии событий (`leading`), trailing-вызов в конце серии по умолчанию и метод `debounceFunc.cancel()` для отмены запланированного вызова.
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 этим контрактом не предусмотрены.