ChatGPT解决这个技术问题 Extra ChatGPT

lodash debounce 在匿名函数中不起作用

您好,我似乎无法弄清楚为什么当直接传递给 keyup 事件时,去抖动功能会按预期工作;但如果我将它包装在匿名函数中,它就不起作用。

我解决了这个问题:http://jsfiddle.net/6hg95/1/

编辑:添加了我尝试过的所有东西。

HTML

<input id='anonFunction'/>
<input id='noReturnAnonFunction'/>
<input id='exeDebouncedFunc'/>
<input id='function'/>
<div id='output'></div>

JAVASCRIPT

$(document).ready(function(){
    $('#anonFunction').on('keyup', function () {
        return _.debounce(debounceIt, 500, false); //Why does this differ from #function
    });
    $('#noReturnAnonFunction').on('keyup', function () {
        _.debounce(debounceIt, 500, false); //Not being executed
    });
    $('#exeDebouncedFunc').on('keyup', function () {
        _.debounce(debounceIt, 500, false)(); //Executing the debounced function results in wrong behaviour
    });
    $('#function').on('keyup', _.debounce(debounceIt, 500, false)); //This is working.
});

function debounceIt(){
    $('#output').append('debounced');
}

anonFunctionnoReturnAnonFunction 不会触发去抖动功能;但最后一个 function 确实会触发。我不明白为什么会这样。有人可以帮我理解吗?

EDIT 好的,所以在#exeDebouncedFunc(你提到的那个)中没有发生去抖动的原因是因为该函数是在匿名函数的范围内执行的,另一个keyup事件将创建一个新函数在另一个匿名范围内;从而触发 debounced 函数的次数与您键入内容的次数一样多(而不是触发一次,这将是预期的行为;参见 #function 的行为)?

您能否解释一下 #anonFunction#function 之间的区别。这又是一个范围问题,为什么其中一个有效而另一个无效?

编辑好的,所以现在我明白为什么会这样了。这就是为什么我需要将它包装在一个匿名函数中的原因:

小提琴:http://jsfiddle.net/6hg95/5/

HTML

<input id='anonFunction'/>
<div id='output'></div>

JAVASCRIPT

(function(){
    var debounce = _.debounce(fireServerEvent, 500, false);

    $('#anonFunction').on('keyup', function () {
        //clear textfield
        $('#output').append('clearNotifications<br/>');
        debounce();
    });

    function fireServerEvent(){
        $('#output').append('serverEvent<br/>');
    }
})();

m
max23_

正如 Palpatim 解释的那样,原因在于 _.debounce(...) 返回一个函数,该函数在被调用时会发挥作用。

因此,在您的 #anonFunction 示例中,您有一个键侦听器,它在被调用时只向调用者返回一个函数,它对来自事件侦听器的返回值不做任何事情。

这是 _.debounce(...) 定义的片段:

_.debounce
function (func, wait, immediate) {
    var timeout;
    return function() {
      var context = this, args = arguments;
      var later = function() {
        timeout = null;
        if (!immediate) func.apply(context, args);
      };
      if (immediate && !timeout) func.apply(context, args);
      clearTimeout(timeout);
      timeout = setTimeout(later, wait);
    };
  } 

您的关键事件侦听器必须调用 _.debounce(...) 的返回函数,或者您可以像在非匿名示例中那样做,并将 _.debounce(...) 调用的返回函数用作您的事件侦听器。


+1 这个解释。基本上是这样的:$('#function').on('keyup', _.debounce(debounceIt, 500, false)); //This is working. 是为什么 debounce 返回一个函数。像这样美丽,Just Makes Sense™
z
zevero

想得更轻松

_.debounce 返回一个去抖函数!因此,而不是考虑

$el.on('keyup'), function(){
   _.debounce(doYourThing,500); //uh I want to debounce this
}

您宁愿调用 debounced 函数

var doYourThingDebounced = _.debounce(doYourThing, 500); //YES, this will always be debounced

$el.on('keyup', doYourThingDebounced);

如果我必须在 keyup 上调用多个函数并且只有其中一个应该被去抖动怎么办?
@bharadhwaj - doYourThingDebounced 是一个函数;您可以将其称为事件处理程序的 part$el.on('keyup', function() { doYourThingDebounced(); doYourOtherThing(); }
P
Palpatim

debounce 不执行该函数,它返回一个内置去抖动功能的函数。

Returns (Function):返回新的去抖动函数。

因此,您的 #function 处理程序实际上是在做正确的事情,方法是返回一个供 jQuery 用作 keyup 处理程序的函数。要修复您的 #noReturnAnonFunction 示例,您只需在函数的上下文中执行 debounced 函数:

$('#noReturnAnonFunction').on('keyup', function () {
    _.debounce(debounceIt, 500, false)(); // Immediately executes
});

但这会在你的 debounce 周围引入一个不必要的匿名函数包装器。


这么多的赞成票,但恕我直言,这是行不通的。在每次按键时,函数 debounceIt 将被转换为去抖动函数并立即执行,效果 debounceIt 将延迟 500 毫秒。每次按键都会重复此操作!所以最后,你的代码相当于 $('#noReturnAnonFunction').on('keyup', function (){setTimeout(debounceIt, 500);}) 没有去抖动......只有延迟。
你说的对。我不认为它在反弹。延迟了
j
jiv-e

您可以像这样返回 debounce 函数:

(function(){
    var debounce = _.debounce(fireServerEvent, 500, false);

    $('#anonFunction').on('keyup', function () {
        //clear textfield
        $('#output').append('clearNotifications<br/>');
        return debounce();
    });

    function fireServerEvent(){
        $('#output').append('serverEvent<br/>');
    }
})();

在这种情况下似乎不需要这样做。不过,类似的想法在另一种情况下帮助了我。
_.debounce 不返回函数,而是返回设置为超时的时间。
根据文档 _.debounce 确实返回了该函数。参考。 lodash.com/docs/#debounce
R
Rachel Newman

在寻找通过尾随调用调用去抖动的解决方案时遇到了这个问题,发现这篇文章确实对我有帮助:https://newbedev.com/lodash-debounce-not-working-in-react 特别是:

对于那些因为油门/去抖不起作用而来到这里的人的解决方案 >with FunctionComponent - 您需要通过 useRef() 存储去抖函数:

export const ComponentName = (value = null) => {
  const [inputValue, setInputValue] = useState(value);

  const setServicesValue = value => Services.setValue(value);

  const setServicesValueDebounced = useRef(_.debounce(setServicesValue, 1000));

  const handleChange = ({ currentTarget: { value } }) => {
    setInputValue(value);
    setServicesValueDebounced.current(value);
  };

  return <input onChange={handleChange} value={inputValue} />;
};

感谢这个瑞秋,这对我有用!
什么是Services.setValue(value);
B
Baishu

更一般地说,如果你想要一个带有尾随行为的去抖动(考虑最后一次点击,或者更有可能是选择输入的最后一次更改),以及第一次点击/更改的视觉反馈,你将面临同样的问题。

这不起作用:

$(document).on('change', "#select", function() {
    $('.ajax-loader').show();
    _.debounce(processSelectChange, 1000);
});

这将是一个解决方案:

$(document).on('change', "#select", function() {
    $('.ajax-loader').show();
});
$(document).on('change', "#select", _.debounce(processSelectChange, 1000));