Пожалуйста, помогите мне решить проблему, как мы можем вернуть отклоненную версию функции ввода. проверьте код ниже:
const steven = () => {console.info('steven')}
const debounce = (fn, timeLimit) => {
// what should come here?
}
const debouncedSteeven = debounce(steven, 5000) // returns a debounced version of the input function
window.addEventListener('scroll', debouncedSteeven);
нет, я хочу запускать функцию Стивена только тогда, когда пользователь делает перерыв более 5 секунд, а затем снова прокручивает.
Проводили ли вы какое-либо исследование debounce или пытались что-то реализовать самостоятельно?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Посмотрите на setTimeout, который в основном делает то, о чем вы просите.
const debounce = (fn, timeLimit) => () => {
clearTimeout(this.timeout);
this.timeout = setTimeout(fn, timeLimit);
};
let myFunc = () => console.info('yo');
let myFuncDebounced = debounce(myFunc);
myFuncDebounced();
myFuncDebounced();
console.info('this will print first cause this aint Tha BOUNCE d!!!');Это не отменено — многократный вызов функции под timeLimit будет по-прежнему выполняться один раз за каждый сделанный вызов.
фиксированный. спасибо, что указали на это
Если я правильно понял, вы хотите, чтобы функция выполнялась, если нет события scroll более X миллисекунд. В этом случае одним из решений является использование setTimeout() и clearTimeout(). Таким образом, каждый раз, когда вызывается функция debounce, timeout сбрасывается, если он уже существует. Реализация будет примерно такой:
// Object to hold the timers by function names.
let timers = {};
const steven = () => {console.info('steven')};
const debounce = (fn, timeLimit) =>
{
return () =>
{
if (timers[fn.name])
clearTimeout(timers[fn.name]);
timers[fn.name] = setTimeout(fn, timeLimit);
}
}
const debouncedSteeven = debounce(steven, 5000);
window.addEventListener('scroll', debouncedSteeven);.as-console {background-color:black !important; color:lime;}<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>Если вместо этого вы хотите выполнить функцию, если между двумя событиями X есть промежуток в scroll миллисекунд, вы можете попробовать это:
// Object to hold last time a debounced method is called.
let lastExec = {};
const steven = () => {console.info('steven')};
const debounce = (fn, timeLimit) =>
{
return () =>
{
if (new Date().getTime() - lastExec[fn.name] > timeLimit)
fn();
lastExec[fn.name] = new Date().getTime();
}
}
const debouncedSteeven = debounce(steven, 5000);
window.addEventListener('scroll', debouncedSteeven);.as-console {background-color:black !important; color:lime;}<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>
<p>text</p>Спасибо за ваш ответ, но он автоматически регистрирует Стивена через некоторое время. Я хочу регистрировать Стивена только после прокрутки пользователя и сделать перерыв более 5 секунд.
@JagdeeshKumar О, понятно, проверьте второй фрагмент в обновленной версии.
Работал на меня. Спасибо!
Я думаю, что лучшее решение с rxjs сначала установите rxjs с помощью npm или yarn. затем создайте наблюдаемое из события прокрутки и передайте оператор debounce, а внутри его функции - оператор таймера, все они импортированы из rxjs.
fromEvent(window, 'scroll')
.pipe(debounce(() => timer(1000))
.subscribe(v => console.info('scrolled'))
этот код будет регистрировать «прокручиваемый» со временем устранения дребезга 1000 мс = 1 сек. также рекомендуется отписываться в конце жизненного цикла компонента или кода, чтобы предотвратить утечку памяти.
Вы можете использовать setTimeout внутри функции более высокого порядка, чтобы запланировать выполнение функции, но затем отменить этого выполнения, если функция вызывается снова.
Кроме того, вы можете хранить и передавать контекст и аргументы, когда был сделан вызов, и вызывать функцию, для которой было выполнено отключение, с ними, чтобы не потерять их. Это позволит вам применить дебаунс к любой функции, а не только к той, которая не использует this и не принимает никаких параметров:
function debounce(fn, limit = 0) {
//this will hold the timer identifier from setTimeout
let timeId;
//return a debounced function
return function _debounced() {
//unschedule any previous execution
clearTimeout(timeId);
//store the arguments
const args = arguments;
//store the context
let ctx = this;
//schedule a new execution after the given time limit
timeId = setTimeout(function() {
//run the function with the context and arguments passed
fn.apply(ctx, args);
}, limit);
}
}
//using parameters
function add(a, b) {
console.info("adding", a, b);
console.info("result", a + b);
}
const debouncedAdd = debounce(add, 1000);
debouncedAdd(1, 2);
debouncedAdd(3, 4);
debouncedAdd(5, 6); //only this gets executed
//using context
const person = {
name: "Alice",
sayHello: debounce(function sayHello() {
console.info("hello, my name is:", this.name)
}, 1000)
}
person.sayHello();
person.name = "Bob";
person.sayHello();
person.name = "Carol";
person.sayHello(); //only this gets executedХорошо, та же идея, что и у меня, но более общий подход. Я просто не могу понять, как удалить мой глобальный объект, используемый для хранения ids, возвращаемого из setTimeout, и теперь я вижу, как это сделать (+1). В любом случае, я думаю, что ОП хотел другого...
Вам нужно вернуть новую функцию, которая будет выполняться через
timeLimitмиллисекунд, т.е. добавить задержку выполнения?