Javascript jQuery 中的限制事件调用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7373023/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 02:00:17  来源:igfitidea点击:

Throttle event calls in jQuery

javascriptjqueryevents

提问by Peter Olson

I have a keyupevent bound to a function that takes about a quarter of a second to complete.

我有一个keyup事件绑定到一个需要大约四分之一秒才能完成的函数。

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

When a user types an entire word, or otherwise presses keys rapidly, the function will be called several times in succession and it will take a while for them all to complete.

当用户输入一个完整的单词或快速按键时,该函数将被连续调用多次,并且需要一段时间才能完成。

Is there a way to throttle the event calls so that if there are several in rapid succession, it only triggers the one that was most recently called?

有没有办法限制事件调用,以便如果有几个快速连续,它只触发最近调用的一个?

回答by josh3736

Take a look at jQuery Debounce.

看看jQuery Debounce

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

回答by Nathan Manousos

Here is a potential solution that doesn't need a plugin. Use a boolean to decide whether to do the keyup callback, or skip over it.

这是一个不需要插件的潜在解决方案。使用布尔值来决定是执行 keyup 回调还是跳过它。

var doingKeyup = false;

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

回答by Michael Scheper

You could also use the excellent Underscore/_library.

你也可以使用优秀的Underscore/_库。

Comments in Josh's answer, currently the most popular, debate whether you should really throttle the calls, or if a debouncer is what you want. The differenceis a bit subtle, but Underscore has both: _.debounce(function, wait, [immediate])and _.throttle(function, wait, [options]).

Josh 的回答中的评论,目前最流行的,辩论是否真的应该限制通话,或者是否需要 debouncer。区别有点微妙,但 Underscore 同时具有:_.debounce(function, wait, [immediate])_.throttle(function, wait, [options]).

If you're not already using Underscore, check it out. It can make your JavaScript much cleaner, and is lightweight enough to give most library haters pause.

如果您还没有使用 Underscore,请检查一下。它可以让你的 JavaScript 更简洁,并且足够轻量级,让大多数库讨厌者停下来。

回答by AntonK

Here's a clean way of doing it with JQuery.

这是使用 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);

回答by Max

Two small generic implementations of throttling approaches. (I prefer to do it through these simple functions rather than adding another jquery plugin)

节流方法的两个小型通用实现。(我更喜欢通过这些简单的函数来完成,而不是添加另一个 jquery 插件)

  1. Waits some time after last call

    This one is useful when we don't want to call for example search function when user keeps typing the query

  1. 最后一次通话后等待一段时间

    当我们不想在用户不断输入查询时调用例如搜索功能时,这个很有用

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. Calls given function not more often than given amount of time

    The following one is useful for flushing logs

  1. 调用给定函数的频率不超过给定的时间

    以下一项对刷新日志很有用

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

Usage is very simple:

用法很简单:

The following one is waiting 2s after the last keystroke in the inputBox and then calls function which should be throttled.

以下是在 inputBox 中的最后一次击键后等待 2 秒,然后调用应该被限制的函数。

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

Here is an example where you can test both: click (CodePen)

这是您可以同时测试的示例:单击 (CodePen)

回答by th3byrdm4n

I came across this question reviewing changes to zurb-foundation. They've added their own methodfor debounce and throttling. It looks like it might be the same as the jquery-debounce @josh3736 mentioned in his answer.

我在zurb-foundation更改时遇到了这个问题。他们添加了自己的去抖动和节流方法。看起来它可能与他的回答中提到的 jquery-debounce @josh3736 相同。

From their 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));

回答by Brian Armstrong

Something like this seems simplest (no external libraries) for a quick solution (note coffeescript):

对于快速解决方案(注意coffeescript),这样的事情似乎最简单(没有外部库):

running = false
$(document).on 'keyup', '.some-class', (e) ->
  return if running
  running = true
  $.ajax
    type: 'POST',
    url: $(this).data('url'),
    data: $(this).parents('form').serialize(),
    dataType: 'script',
    success: (data) ->
      running = false