46 votes

Accélérer les appels d'événements dans jQuery

J'ai un keyup lié à une fonction qui prend environ un quart de seconde pour se terminer.

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

Lorsqu'un utilisateur tape un mot entier ou appuie rapidement sur des touches, la fonction sera appelée plusieurs fois de suite et il faudra un certain temps pour qu'elle se termine.

Existe-t-il un moyen de limiter les appels d'événements de sorte que, s'il y en a plusieurs en succession rapide, seul celui qui a été appelé le plus récemment soit déclenché ?

70voto

josh3736 Points 41911

Jetez un coup d'œil à jQuery Debounce .

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

13voto

Nathan Manousos Points 2968

Voici une solution potentielle qui ne nécessite pas de plugin. Utilisez un booléen pour décider de faire le rappel du keyup ou de l'ignorer.

var doingKeyup = false;

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

6voto

Michael Scheper Points 552

Vous pouvez également utiliser l'excellent Underscore/_ bibliothèque.

Commentaires dans l'article de Josh réponse les plus populaires actuellement, débattent de la question de savoir s'il faut vraiment étrangler les appels, ou si c'est un débouteur qu'il faut utiliser. La différence est un peu subtile, mais Underscore a les deux : _.debounce(function, wait, [immediate]) y _.throttle(function, wait, [options]) .

Si vous n'utilisez pas encore Underscore, allez-y. Il peut rendre votre JavaScript beaucoup plus propre, et il est suffisamment léger pour faire réfléchir la plupart des personnes qui détestent les bibliothèques.

2voto

AntonK Points 326

Voici une façon propre de le faire avec 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);

1voto

Max Points 271

Deux petites mises en œuvre génériques d'approches d'étranglement. (Je préfère le faire à travers ces fonctions simples plutôt que d'ajouter un autre plugin jquery)

  1. Attend un certain temps après le dernier appel

    Cette fonction est utile lorsque nous ne voulons pas appeler par exemple la fonction de recherche lorsque l'utilisateur continue à taper la requête.

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

  2. Appelle une fonction donnée pas plus souvent qu'un temps donné

    Le suivant est utile pour vider les journaux.

    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'utilisation est très simple :

Le suivant attend 2s après la dernière frappe dans l'inputBox et appelle ensuite la fonction qui doit être accélérée.

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

Voici un exemple où vous pouvez tester les deux : cliquer (CodePen)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X