【问题标题】:lodash debounce not working in anonymous functionlodash debounce 在匿名函数中不起作用
【发布时间】:2014-08-09 23:21:27
【问题描述】:

您好,我似乎无法弄清楚为什么当直接传递给 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 确实会触发。我不明白为什么会这样。谁能帮我理解一下?

编辑 好的,所以在#exeDebouncedFunc(你提到的那个)中没有发生去抖动的原因是因为该函数是在匿名函数的范围内执行的,另一个keyup事件将在另一个匿名范围内创建一个新函数;因此在您键入内容时多次触发去抖动功能(而不是触发一次,这将是预期的行为;参见#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/>');
    }
})();

【问题讨论】:

    标签: javascript jquery lodash


    【解决方案1】:

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

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

    这是_.debounce(...)定义的sn-p:

    _.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™
    【解决方案2】:

    想得更轻松

    _.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(); }
    【解决方案3】:

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

    退货

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

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

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

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

    【讨论】:

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

    你可以像这样返回去抖动函数:

    (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
    【解决方案5】:

    在寻找使用尾随调用调用去抖动的解决方案时遇到了这个问题,发现这篇文章对我很有帮助: https://newbedev.com/lodash-debounce-not-working-in-react 具体来说:

    为那些因为油门/去抖不起作用而来到这里的人的解决方案>使用 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);
    【解决方案6】:

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

    这不起作用:

    $(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));
    

    【讨论】:

      猜你喜欢
      • 2018-05-28
      • 2019-04-02
      • 1970-01-01
      • 1970-01-01
      • 2021-09-19
      • 2019-04-08
      • 2016-08-10
      • 2017-04-02
      • 2019-09-01
      相关资源
      最近更新 更多