lodash debounce funktioniert nicht in anonymer Funktion


70

Hallo, ich kann anscheinend nicht herausfinden, warum die Entprellungsfunktion wie erwartet funktioniert, wenn sie direkt an ein Keyup-Ereignis übergeben wird. aber es funktioniert nicht, wenn ich es in eine anonyme Funktion einbinde.

Ich habe Probleme mit dem Problem: http://jsfiddle.net/6hg95/1/

EDIT: Alle Dinge hinzugefügt, die ich versucht habe.

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

anonFunctionund noReturnAnonFunctionlöst die Entprellungsfunktion nicht aus; aber der letzte functionfeuert. Ich verstehe nicht, warum das so ist. Kann mir bitte jemand helfen, das zu verstehen?

BEARBEITEN Ok, der Grund dafür, dass das Entprellen in #exeDebounceFunc (dem, auf das Sie verweisen) nicht erfolgt, liegt darin, dass die Funktion im Bereich der anonymen Funktion ausgeführt wird und ein anderes Keyup-Ereignis eine neue Funktion in einem anderen anonymen Bereich erstellt. also die entprellte Funktion so oft auslösen, wie Sie etwas eingeben (anstatt einmal zu feuern, was das erwartete Verhalten wäre; siehe unten #function)?

Können Sie bitte den Unterschied zwischen #anonFunctionund erklären #function. Geht es hier wieder darum, warum einer von ihnen funktioniert und der andere nicht?

EDIT Ok, jetzt verstehe ich, warum das passiert. Und hier ist, warum ich es in eine anonyme Funktion einwickeln musste:

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

Antworten:


67

Wie Palpatim erklärte, liegt der Grund in der Tatsache, dass _.debouce(...)eine Funktion zurückgegeben wird, die beim Aufrufen ihre Magie entfaltet.

Daher haben Sie in Ihrem #anonFunctionBeispiel einen Schlüssel-Listener, der beim Aufrufen nur eine Funktion an den Aufrufer zurückgibt, die nichts mit den Rückgabewerten des Ereignis-Listeners tut.

Dies ist ein Ausschnitt aus der _.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);
    };
  } 

Ihr wichtiger Ereignis-Listener muss die zurückgegebene Funktion von aufrufen _.debounce(...), oder Sie können wie in Ihrem nicht anonymen Beispiel die vom _.debounce(...)Aufruf zurückgegebene Funktion als Ereignis-Listener verwenden.


2
+1 für diese Erklärung. Grundsätzlich gilt: $('#function').on('keyup', _.debounce(debounceIt, 500, false)); //This is working. WARUM Debounce eine Funktion zurückgibt. Es ist so schön und macht einfach Sinn ™
Metagrapher

42

Denken Sie einfacher

_.debounce gibt eine entprellte Funktion zurück! Also anstatt in Begriffen zu denken

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

Sie rufen stattdessen lieber die entprellte Funktion auf

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

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

2
Was ist, wenn ich mehrere Funktionen aufrufen muss keyupund nur eine davon entprellt werden soll?
Bharadhwaj

41

debounce führt die Funktion nicht aus, sondern gibt eine Funktion mit der darin enthaltenen Debounciness zurück.

Kehrt zurück

(Funktion) : Gibt die neue entprellte Funktion zurück.

Ihr #functionHandler macht also tatsächlich das Richtige, indem er eine Funktion zurückgibt, die von jQuery als Keyup-Handler verwendet wird. Um Ihr #noReturnAnonFunctionBeispiel zu korrigieren, können Sie die entprellte Funktion einfach im Kontext Ihrer Funktion ausführen:

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

Aber das führt einen unnötigen anonymen Funktions-Wrapper um Ihre Entprellung ein.


17
So viele positive Stimmen, aber imho kann das nicht funktionieren. Bei jeder Eingabe wird die Funktion debounceIt in eine entprellte Funktion umgewandelt UND sofort ausgeführt, so dass sich debounceIt um 500 ms verzögert. Dies wird bei jedem Tastendruck wiederholt! Am Ende entspricht Ihr Code also $ ('# noReturnAnonFunction'). On ('keyup', function () {setTimeout (debounceIt, 500);}) Kein Entprellen ... nur Verzögerung.
Zevero

Du hast recht. Ich glaube nicht, dass es entprellt. Es verzögert sich
vuquanghoang

6

Sie können die Entprellungsfunktion wie folgt zurückgeben:

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

Es scheint, dass dies in dieser Situation nicht erforderlich ist. Eine ähnliche Idee hat mir jedoch in einer anderen Situation geholfen.
Jiv-E

_.debounce gibt die Funktion nicht zurück, sondern die Zeit, für die das Timeout eingestellt ist.
Pilzanthrax

Laut Dokumentation gibt _.debounce die Funktion zurück. ref. lodash.com/docs/#debounce
Sunil Sharma

0

Wenn Sie eine Entprellung mit einem nachlaufenden Verhalten (Konten für den letzten Klick oder wahrscheinlicher die letzte Änderung an einer ausgewählten Eingabe) und ein visuelles Feedback für den ersten Klick / die erste Änderung wünschen, sind Sie im Allgemeinen mit demselben Problem konfrontiert.

Das funktioniert nicht:

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

Dies wäre eine Lösung:

$(document).on('change', "#select", function() {
    $('.ajax-loader').show();
});
$(document).on('change', "#select", _.debounce(processSelectChange, 1000));
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.