web-dev-qa-db-fra.com

lodash debounce ne fonctionne pas en fonction anonyme

Bonjour, je n'arrive pas à comprendre pourquoi la fonction anti-rebond fonctionne comme prévu lorsqu'elle est transmise directement à un événement keyup. mais cela ne fonctionne pas si je l'enveloppe dans une fonction anonyme.

J'ai violon du problème: http://jsfiddle.net/6hg95/1/

EDIT: Ajouté toutes les choses que j'ai essayées.

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 et noReturnAnonFunction ne lance pas la fonction anti-rebond; mais la dernière function tire. Je ne comprends pas pourquoi c'est. Quelqu'un peut-il m'aider s'il vous plaît à comprendre cela?

EDIT Ok, la raison pour laquelle le rebond ne se produit pas dans #exeDebounceFunc (celui que vous référez) est que la fonction est exécutée dans le cadre de la fonction anonyme et qu'un autre événement keyup créera un nouvelle fonction dans un autre champ d'application anonyme; lancez donc la fonction debounce autant de fois que vous tapez quelque chose (au lieu de tirer une fois, quel serait le comportement attendu; voir page précédente de #function)?

Pouvez-vous s'il vous plaît expliquer la différence entre #anonFunction et le #function. Est-ce à nouveau une question de savoir pourquoi l’un d’entre eux fonctionne et l’autre ne fonctionne pas?

EDIT Ok, je comprends maintenant pourquoi cela se produit. Et voici pourquoi je devais l'envelopper dans une fonction anonyme:

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

Comme Palpatim l'a expliqué, la raison réside dans le fait que _.debouce(...) renvoie une fonction, ce qui, une fois appelée, est magique.

Par conséquent, dans votre exemple #anonFunction, vous avez un écouteur de clé qui, lorsqu'il est appelé, ne renvoie qu'une fonction à l'appelant, qui ne fait rien avec les valeurs de retour de l'écouteur d'événements.

Voici un extrait de la définition de _.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);
    };
  } 

Votre écouteur d'événements clé doit appeler la fonction renvoyée à partir de _.debounce(...). Vous pouvez également procéder comme dans votre exemple non anonyme et utiliser la fonction renvoyée à partir de l'appel _.debounce(...) comme écouteur d'événements.

46
Michael Dahl

debounce n'exécute pas la fonction, il retourne une fonction avec le défaut intégré dans celle-ci.

Résultats

(Fonction): Renvoie la nouvelle fonction décompressée.

Donc, votre gestionnaire #function fait réellement la bonne chose en renvoyant une fonction à utiliser par jQuery en tant que gestionnaire keyup. Pour corriger votre exemple #noReturnAnonFunction, vous pouvez simplement exécuter la fonction debounce dans le contexte de votre fonction:

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

Mais cela introduit une enveloppe de fonction anonyme inutile autour de votre rebond.

34
Palpatim

Penser plus facilement

_.debounce retourne une fonction debounce!

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

vous appelez plutôt la fonction debounce à la place

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

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

Vous pouvez retourner la fonction anti-rebond comme ceci:

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

Plus généralement, si vous souhaitez un comportement anti-rebond avec un comportement de fin (comptes du dernier clic, ou plus probablement du dernier changement sur une entrée sélectionnée) et un retour visuel du premier clic/changement, vous êtes confronté au même problème.

Cela ne fonctionne pas:

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

Ce serait une solution:

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