返回输入函数的debounced版本[重复]

问题描述 投票:-1回答:4

这个问题在这里已有答案:

请帮我解决问题,我们怎样才能返回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);
javascript
4个回答
1
投票

如果我理解正确,如果没有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>

1
投票

您可以在更高阶函数中使用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

-1
投票

我认为最好的解决方案是使用rxjs首先安装带有npm或yarn的rxjs。然后从滚动事件中创建一个observable,并在debounce操作符和pipe函数内部创建一个定时器操作符,所有这些操作符都是从rxjs导入的。

fromEvent(window, 'scroll')
  .pipe(debounce(() => timer(1000))
  .subscribe(v => console.log('scrolled'))

此代码将以“滚动”记录,去抖时间为1000毫秒= 1秒。它还建议在组件生命周期或代码的末尾取消描述,以防止内存泄漏


-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!!!');
© www.soinside.com 2019 - 2024. All rights reserved.