这个问题在这里已有答案:
请帮我解决问题,我们怎样才能返回debounced版本的输入功能。检查以下代码:
const steven = () => {console.log('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);
如果我理解正确,如果没有scroll
事件超过X
毫秒,你想要执行该函数。在这种情况下,一种解决方案是使用setTimeout()
和clearTimeout()
。所以每次调用debounced函数时,如果timeout
已经存在,则重置。实现将是这样的:
// Object to hold the timers by function names.
let timers = {};
const steven = () => {console.log('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.log('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>
您可以在更高阶函数中使用setTimeout
来计划函数的执行,但如果再次调用该函数,则取消该执行。
此外,您可以存储和传递调用时的上下文和参数,并使用这些调用debounced函数以便不丢失它们。这将允许您对任何函数应用去抖动,不仅适用于不使用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.log("adding", a, b);
console.log("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.log("hello, my name is:", this.name)
}, 1000)
}
person.sayHello();
person.name = "Bob";
person.sayHello();
person.name = "Carol";
person.sayHello(); //only this gets executed
我认为最好的解决方案是使用rxjs首先安装带有npm或yarn的rxjs。然后从滚动事件中创建一个observable,并在debounce操作符和pipe函数内部创建一个定时器操作符,所有这些操作符都是从rxjs导入的。
fromEvent(window, 'scroll')
.pipe(debounce(() => timer(1000))
.subscribe(v => console.log('scrolled'))
此代码将以“滚动”记录,去抖时间为1000毫秒= 1秒。它还建议在组件生命周期或代码的末尾取消描述,以防止内存泄漏
看看setTimeout
,它基本上可以满足您的要求。
const debounce = (fn, timeLimit) => () => {
clearTimeout(this.timeout);
this.timeout = setTimeout(fn, timeLimit);
};
let myFunc = () => console.log('yo');
let myFuncDebounced = debounce(myFunc);
myFuncDebounced();
myFuncDebounced();
console.log('this will print first cause this aint Tha BOUNCE d!!!');