lodash debounce不能在匿名函数中工作

时间:2014-06-19 12:10:21

标签: javascript jquery lodash

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

我有问题: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的beviour?)

请解释#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/>');
    }
})();

6 个答案:

答案 0 :(得分:48)

正如Palpatim所解释的那样,原因在于_.debouce(...)返回一个函数,该函数在被调用时会产生魔力。

因此,在#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 :(得分:34)

debounce没有执行该函数,它返回一个内置了debounciness的函数。

  

<强>返回

     

(功能):返回新的去抖动功能。

所以你的#function处理程序实际上正在做正确的事情,通过返回一个由jQuery用作keyup处理程序的函数。要修复您的#noReturnAnonFunction示例,您只需在函数的上下文中执行去抖动函数:

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

但那引入了一个不必要的匿名函数包装你的辩护。

答案 2 :(得分:25)

想想更轻松

_.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);

答案 3 :(得分:6)

你可以像这样返回去抖功能:

(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/>');
    }
})();

答案 4 :(得分:1)

在寻找使用尾随调用调用去抖动的解决方案时遇到了这个问题,发现这篇文章对我很有帮助: 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} />;
};

答案 5 :(得分:0)

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

这不起作用:

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