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

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

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

我该怎么做呢?


当前回答

基于CMS的答案,它只是忽略了不改变值的关键事件。

var delay = (function(){
    var timer = 0;
    return function(callback, ms){
      clearTimeout (timer);
      timer = setTimeout(callback, ms);
    };
})(); 

var duplicateFilter=(function(){
  var lastContent;
  return function(content,callback){
    content=$.trim(content);
    if(content!=lastContent){
      callback(content);
    }
    lastContent=content;
  };
})();

$("#some-input").on("keyup",function(ev){

  var self=this;
  delay(function(){
    duplicateFilter($(self).val(),function(c){
        //do sth...
        console.log(c);
    });
  }, 1000 );


})

其他回答

解释

使用变量存储超时函数。然后使用clearTimeout()清除该变量的任何活动超时函数,然后使用setTimeout()再次设置活动超时函数。我们首先运行clearTimeout(),因为如果用户键入“hello”,我们希望函数在用户按下“o”键后不久运行(而不是每个字母一次)。

演示工作

超级简单的方法,设计用于在用户在文本字段中输入完成后运行一个函数…

$(document).ready(function(e) { var timeout; var delay = 2000; // 2 seconds $('.text-input').keyup(function(e) { $('#status').html("User started typing!"); if(timeout) { clearTimeout(timeout); } timeout = setTimeout(function() { myFunction(); }, delay); }); function myFunction() { $('#status').html("Executing function for user!"); } }); <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> Status: <span id="status">Default Status</span><br> <textarea name="text-input" class="text-input"></textarea>

这是一个沿着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。

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

如果你想在类型完成后搜索,使用一个全局变量来保存setTimout调用返回的超时,如果它还没有发生,就用clearTimeout取消它,这样它就不会触发超时,除非在最后一个keyup事件

var globalTimeout = null;  
$('#id').keyup(function(){
  if(globalTimeout != null) clearTimeout(globalTimeout);  
  globalTimeout =setTimeout(SearchFunc,200);  
}   
function SearchFunc(){  
  globalTimeout = null;  
  //ajax code
}

或者使用匿名函数:

var globalTimeout = null;  
$('#id').keyup(function() {
  if (globalTimeout != null) {
    clearTimeout(globalTimeout);
  }
  globalTimeout = setTimeout(function() {
    globalTimeout = null;  

    //ajax code

  }, 200);  
}   

将CMS的答案与Miguel的答案相结合,产生了允许并发延迟的健壮解决方案。

var delay = (function(){
    var timers = {};
    return function (callback, ms, label) {
        label = label || 'defaultTimer';
        clearTimeout(timers[label] || 0);
        timers[label] = setTimeout(callback, ms);
    };
})();

当您需要单独延迟不同的操作时,请使用第三个参数。

$('input.group1').keyup(function() {
    delay(function(){
        alert('Time elapsed!');
    }, 1000, 'firstAction');
});

$('input.group2').keyup(function() {
    delay(function(){
        alert('Time elapsed!');
    }, 1000, '2ndAction');
});

Use

mytimeout = setTimeout( expression, timeout );

其中expression是要运行的脚本,timeout是在它运行之前等待的时间(以毫秒为单位)——这不会暂停脚本,而是简单地延迟该部分的执行,直到超时完成。

clearTimeout(mytimeout);

将重置/清除超时,这样它就不会在表达式中运行脚本(就像取消),只要它还没有被执行。