在jQuery中调用事件调用

时间:2011-09-10 16:26:27

标签: javascript jquery events

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

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

当用户键入整个单词或以其他方式快速按键时,该功能将连续多次调用,并且需要一段时间才能完成。

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

7 个答案:

答案 0 :(得分:59)

看看jQuery Debounce

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

答案 1 :(得分:8)

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

var doingKeyup = false;

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

答案 2 :(得分:3)

您还可以使用优秀的Underscore/_库。

Josh answer中的评论,目前最受欢迎的辩论是,你是否应该真正限制通话,或者是否是你想要的去抖动。 The difference有点微妙,但是下划线同时包含:_.debounce(function, wait, [immediate])_.throttle(function, wait, [options])

如果您尚未使用下划线,请查看。它可以使你的JavaScript更清晰,并且足够轻巧,可以让大多数图书馆人员停下来。

答案 3 :(得分:1)

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

答案 4 :(得分:0)

我遇到了这个问题,审核了对的更改。他们added their own method进行去抖动和限制。看起来它可能和他在答案中提到的jquery-debounce @ josh3736相同。

从他们的网站:

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

答案 5 :(得分:0)

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

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

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

        int size = Account_Number.size();
        for (int i = 1; i <= size; i++) {
            stmt.setString(i, Account_Number.get(i-1));
        }
  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);
  }
}

用法非常简单:

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

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

以下是您可以同时测试这两个示例的示例:click (CodePen)

答案 6 :(得分:-2)

这样的东西似乎最简单(没有外部库)快速解决方案(注意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