wake-up-neo.net

Drosseln Sie Ereignisaufrufe in jQuery

Ich habe ein keyup -Ereignis, das an eine Funktion gebunden ist, die etwa eine Viertelsekunde dauert.

$("#search").keyup(function() {
  //code that takes a little bit to complete
});

Wenn ein Benutzer ein ganzes Wort eingibt oder auf andere Weise schnell andere Tasten drückt, wird die Funktion mehrmals hintereinander aufgerufen, und es dauert eine Weile, bis alle beendet sind.

Gibt es eine Möglichkeit, die Ereignisaufrufe zu drosseln, so dass, wenn es mehrere in schneller Folge gibt, nur der Anruf ausgelöst wird, der zuletzt aufgerufen wurde?

40
Peter Olson

Werfen Sie einen Blick auf jQuery Debounce .

$('#search').keyup($.debounce(function() {
    // Will only execute 300ms after the last keypress.
}, 300));
58
josh3736

Hier ist eine mögliche Lösung, die kein Plugin benötigt. Verwenden Sie einen Boolean-Befehl, um zu entscheiden, ob Sie den Keyup-Callback ausführen oder ihn überspringen möchten.

var doingKeyup = false;

$('input').keyup(function(){
    if(!doingKeyup){
        doingKeyup=true;
        // slow process happens here
        doingKeyup=false;
    }
});
8
Nathan Manousos

Sie können auch die ausgezeichnete Underscore/_ -Bibliothek verwenden.

Kommentare in Josh's answer , das derzeit am beliebtesten ist, debattieren, ob Sie die Anrufe wirklich drosseln sollen oder ob Sie einen Debouncer wollen. Der Unterschied ist etwas subtil, aber Unterstrich hat beides: _.debounce(function, wait, [immediate]) und _.throttle(function, wait, [options]) .

Wenn Sie Underscore nicht bereits verwenden, probieren Sie es aus. Es kann Ihr JavaScript viel sauberer machen und ist leicht genug, um den meisten Bibliothekshassern eine Pause zu machen.

3
Michael Scheper

Hier ist eine saubere Möglichkeit, dies mit JQuery zu tun.

    /* delayed onchange while typing jquery for text boxes widget
    usage:
        $("#SearchCriteria").delayedChange(function () {
            DoMyAjaxSearch();
        });

    */
    (function ($) {
        $.fn.delayedChange = function (options) {
            var timer;
            var o;

            if (jQuery.isFunction(options)) {
                o = { onChange: options };
            }
            else
                o = options;

            o = $.extend({}, $.fn.delayedChange.defaultOptions, o);

            return this.each(function () {
                var element = $(this);
                element.keyup(function () {
                    clearTimeout(timer);
                    timer = setTimeout(function () {
                        var newVal = element.val();
                        newVal = $.trim(newVal);
                        if (element.delayedChange.oldVal != newVal) {
                            element.delayedChange.oldVal = newVal;
                            o.onChange.call(this);
                        }

                    }, o.delay);
                });
            });


        };

        $.fn.delayedChange.defaultOptions = {
            delay: 1000,
            onChange: function () { }
        }

        $.fn.delayedChange.oldVal = "";


    })(jQuery);
1
AntonK

Zwei kleine generische Implementierungen von Throttling-Ansätzen. (Ich ziehe es vor, diese einfachen Funktionen zu verwenden, anstatt ein weiteres Jquery-Plugin hinzuzufügen.)

  1. Wartet einige Zeit nach dem letzten Anruf

    Dies ist hilfreich, wenn Sie beispielsweise keine Suchfunktion aufrufen möchten, wenn der Benutzer die Abfrage weiter eingibt

function throttle(time, func) {
  if (!time || typeof time !== "number" || time < 0) {
      return func;
  }

  var throttleTimer = 0;

  return function() {
    var args = arguments;
    clearTimeout(throttleTimer);
    throttleTimer = setTimeout(function() {
      func.apply(null, args);
    }, time);
  }
}
  1. Aufrufe gegebene Funktion nicht öfter als gegebene Zeitdauer

    Das folgende ist nützlich, um Protokolle zu leeren

function throttleInterval(time, func) {
  if (!time || typeof time !== "number" || time < 0) {
      return func;
  }

  var throttleTimer = null;
  var lastState = null;
  var eventCounter = 0;
  var args = [];

  return function() {
    args = arguments;
    eventCounter++;
    if (!throttleTimer) {
      throttleTimer = setInterval(function() {
        if (eventCounter == lastState) {
          clearInterval(throttleTimer);
          throttleTimer = null;
          return;
        }

        lastState = eventCounter;
        func.apply(null, args);
      }, time);
    }
  }
}

Die Verwendung ist sehr einfach:

Der folgende wartet 2s nach dem letzten Tastendruck in der inputBox und ruft dann eine Funktion auf, die gedrosselt werden sollte.

$("#inputBox").on("input", throttle(2000, function(evt) {
  myFunctionToThrottle(evt);
}));

Hier ist ein Beispiel, in dem Sie beide testen können: click (CodePen)

0
Max

Ich bin auf diese Frage gestoßen und habe die Änderungen an zurb-foundation überprüft. Sie haben ihre eigene Methode hinzugefügt für Debounce und Throttling. Es sieht so aus, als könnte es dasselbe sein wie das in seiner Antwort erwähnte jquery-debounce @ josh3736.

Von ihrer Website: 

// Debounced button click handler
$('.button').on('click', Foundation.utils.debounce(function(e){
  // Handle Click
}, 300, true));

// Throttled resize function
$(document).on('resize', Foundation.utils.throttle(function(e){
  // Do responsive stuff
}, 300));
0
th3byrdm4n