我有一个搜索域。现在它会搜索每一个按键。所以如果有人输入“Windows”,它会用AJAX搜索每个键:“W”,“Wi”,“Win”,“Wind”,“Windo”,“Window”,“Windows”。

我想有一个延迟,所以它只在用户停止输入200毫秒时搜索。

在keyup函数中没有这个选项,我尝试了setTimeout,但它不起作用。

我该怎么做呢?


当前回答

我很惊讶,没有人提到多重输入的问题在CMS的非常好的剪辑。

基本上,你必须为每个输入分别定义延迟变量。否则,如果有人把文本放在第一个输入,并迅速跳转到其他输入并开始输入,第一个的回调将不会被调用!

下面是我根据其他答案编写的代码:

(function($) {
    /**
     * KeyUp with delay event setup
     * 
     * @link http://stackoverflow.com/questions/1909441/jquery-keyup-delay#answer-12581187
     * @param function callback
     * @param int ms
     */
    $.fn.delayKeyup = function(callback, ms){
            $(this).keyup(function( event ){
                var srcEl = event.currentTarget;
                if( srcEl.delayTimer )
                    clearTimeout (srcEl.delayTimer );
                srcEl.delayTimer = setTimeout(function(){ callback( $(srcEl) ); }, ms);
            });

        return $(this);
    };
})(jQuery);

该解决方案将setTimeout引用保留在输入的delayTimer变量中。它还像fazzyx建议的那样将元素的引用传递给回调。

在IE6, 8(comp - 7), 8和Opera 12.11中测试。

其他回答

延迟函数调用每个按键。 jQuery 1.7.1或更高版本

jQuery.fn.keyupDelay = function( cb, delay ){
  if(delay == null){
    delay = 400;
  }
  var timer = 0;
  return $(this).on('keyup',function(){
    clearTimeout(timer);
    timer = setTimeout( cb , delay );
  });
}

用法:$ (' # searchBox”)。keyupDelay(cb);

今天看到这个有点晚,但我想把它放在这里,以防有人需要。只需将函数分离以使其可重用。下面的代码在输入stop后将等待1/2秒。

    var timeOutVar
$(selector).on('keyup', function() {

                    clearTimeout(timeOutVar);
                    timeOutVar= setTimeout(function(){ console.log("Hello"); }, 500);
                });
// Get an global variable isApiCallingInProgress

//  check isApiCallingInProgress 
if (!isApiCallingInProgress) {
// set it to isApiCallingInProgress true
      isApiCallingInProgress = true;

      // set timeout
      setTimeout(() => {
         // Api call will go here

        // then set variable again as false
        isApiCallingInProgress = false;     
      }, 1000);
}

好吧,我也做了一段代码限制高频ajax请求由Keyup / Keydown。看看这个:

https://github.com/raincious/jQueue

像这样提问:

var q = new jQueue(function(type, name, callback) {
    return $.post("/api/account/user_existed/", {Method: type, Value: name}).done(callback);
}, 'Flush', 1500); // Make sure use Flush mode.

并像这样绑定事件:

$('#field-username').keyup(function() {
    q.run('Username', this.val(), function() { /* calling back */ });
});

这是一个沿着CMS的路线的解决方案,但为我解决了几个关键问题:

支持多输入,延迟可以并发运行。 忽略没有改变值的键事件(如Ctrl, Alt+Tab)。 解决竞态条件(当执行回调且值已更改时)。

var delay = (function() {
    var timer = {}
      , values = {}
    return function(el) {
        var id = el.form.id + '.' + el.name
        return {
            enqueue: function(ms, cb) {
                if (values[id] == el.value) return
                if (!el.value) return
                var original = values[id] = el.value
                clearTimeout(timer[id])
                timer[id] = setTimeout(function() {
                    if (original != el.value) return // solves race condition
                    cb.apply(el)
                }, ms)
            }
        }
    }
}())

用法:

signup.key.addEventListener('keyup', function() {
    delay(this).enqueue(300, function() {
        console.log(this.value)
    })
})

代码以我喜欢的风格编写,您可能需要添加一堆分号。

需要记住的事情:

一个唯一的id是基于表单id和输入名称生成的,所以它们必须是定义的和唯一的,或者您可以根据您的情况进行调整。 Delay返回一个易于扩展以满足自己需要的对象。 用于延迟的原始元素被绑定到回调,因此这可以按预期工作(如示例所示)。 在第二次验证中忽略空值。 注意enqueue,它首先需要毫秒,我更喜欢这样,但您可能想要切换参数以匹配setTimeout。

我使用的解决方案增加了另一个层次的复杂性,例如,允许您取消执行,但这是一个很好的基础。