it-swarm.it

Chiamate di eventi di limitazione in jQuery

Ho un evento keyup associato a una funzione che richiede circa un quarto di secondo per essere completata.

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

Quando un utente digita un'intera parola, o altrimenti preme rapidamente i tasti, la funzione verrà chiamata più volte in successione e ci vorrà un po 'prima che tutti vengano completati.

C'è un modo per limitare le chiamate di eventi in modo che se ci sono molti in rapida successione, si innesca solo quello che è stato chiamato più recentemente?

40
Peter Olson

Dai un'occhiata a jQuery Debounce .

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

Ecco una potenziale soluzione che non ha bisogno di un plugin. Utilizzare un booleano per decidere se eseguire la richiamata di keyup o ignorarla.

var doingKeyup = false;

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

Puoi anche usare l'eccellente Underscore/_ library.

I commenti in Josh answer , attualmente il più popolare, discutono se dovresti davvero limitare le chiamate o se un debouncer è quello che vuoi. La differenza è un po 'sottile, ma Underscore ha sia: _.debounce(function, wait, [immediate]) and _.throttle(function, wait, [options]) .

Se non stai già utilizzando Underscore, dai un'occhiata. Può rendere il tuo JavaScript molto più pulito ed è abbastanza leggero da far sospendere la maggior parte degli hacker della biblioteca.

3
Michael Scheper

Ecco un modo pulito per farlo con JQuery.

    /* 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

Due piccole implementazioni generiche di approcci di regolazione. (Preferisco farlo attraverso queste semplici funzioni piuttosto che aggiungere un altro plug-in jquery)

  1. Aspetta un po 'di tempo dopo l'ultima chiamata

    Questo è utile quando non vogliamo chiamare per esempio la funzione di ricerca quando l'utente continua a digitare la query

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. Le chiamate fornite non funzionano più di una quantità di tempo prestabilita

    Il seguente è utile per eseguire il flushing dei log

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

L'utilizzo è molto semplice:

Quello che segue è in attesa di 2 secondi dopo l'ultima battuta nell'inputBox e quindi chiama la funzione che dovrebbe essere limitata.

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

Ecco un esempio in cui puoi testare entrambi: click (CodePen)

0
Max

Mi sono imbattuto in questa domanda rivedendo le modifiche a zurb-foundation . Hanno aggiunto il proprio metodo per il debounce e la limitazione. Sembra che potrebbe essere lo stesso del jquery-debounce @ josh3736 menzionato nella sua risposta.

Dal loro sito web: 

// 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