Search code examples
javascriptjquerylodash

lodash debounce not working in anonymous function


Hello I cannot seem to figure out why the debounce function works as expected when passed directly to a keyup event; but it does not work if I wrap it inside an anonymous function.

I have fiddle of the problem: http://jsfiddle.net/6hg95/1/

EDIT: Added all the things I tried.

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

anonFunction and noReturnAnonFunction does not fire the debounce function; but the last function does fire. I do not understand why this is. Can anybody please help me understand this?

EDIT Ok, so the reason that the debounce does not happen in #exeDebouncedFunc (the one you refer) is because the function is executed in the scope of the anonymous function and another keyup event will create a new function in another anonymous scope; thus firing the debounced function as many times as you type something (instead of firing once which would be the expected behaviour; see beviour of #function)?

Can you please explain the difference between #anonFunction and the #function. Is this again a matter of scoping why one of them works and the other does not?

EDIT Ok, so now I understand why this is happening. And here is why I needed to wrap it inside an anonymous function:

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

Solution

  • As Palpatim explained, the reason lies in the fact that _.debounce(...) returns a function, which when invoked does its magic.

    Therefore in your #anonFunction example, you have a key listener, which when invoked does nothing but return a function to the invoker, which does nothing with the return values from the event listener.

    This is a snippet of the _.debounce(...) definition:

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

    Your key event listener must invoke the returned function from _.debounce(...), or you can do as in your non-anonymous example and use the returned function from the _.debounce(...) call as your event listener.