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

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

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

我该怎么做呢?


当前回答

我使用这个小函数也是出于同样的目的,在用户停止输入一段特定的时间后,或者在以高速率触发的事件中执行一个函数,比如resize:

function delay(callback, ms) { var timer = 0; return function() { var context = this, args = arguments; clearTimeout(timer); timer = setTimeout(function () { callback.apply(context, args); }, ms || 0); }; } // Example usage: $('#input').keyup(delay(function (e) { console.log('Time elapsed!', this.value); }, 500)); <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <label for="input">Try it: <input id="input" type="text" placeholder="Type something here..."/> </label>

工作原理:

delay函数将返回一个内部处理单个计时器的包装函数,在每次执行时,计时器都会根据所提供的时间延迟重新启动,如果在此时间之前发生多次执行,计时器将重置并重新启动。

当计时器最终结束时,执行回调函数,传递原始上下文和参数(在本例中,是jQuery的事件对象和DOM元素)。

更新2019-05-16

我在现代环境中使用ES5和ES6特性重新实现了该功能:

function delay(fn, ms) {
  let timer = 0
  return function(...args) {
    clearTimeout(timer)
    timer = setTimeout(fn.bind(this, ...args), ms || 0)
  }
}

该实现包含一组测试。

对于更复杂的东西,看看jQuery Typewatch插件。

其他回答

CMS的回答又有了一点改进。为了方便地允许单独的延迟,您可以使用以下方法:

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

如果你想重复使用相同的延迟,就这样做

var delay = makeDelay(250);
$(selector1).on('keyup', function() {delay(someCallback);});
$(selector2).on('keyup', function() {delay(someCallback);});

如果你想分开延迟,可以这样做

$(selector1).on('keyup', function() {makeDelay(250)(someCallback);});
$(selector2).on('keyup', function() {makeDelay(250)(someCallback);});

使用标签延迟多函数调用

这是我的解决方案。它会延迟你想要的任何函数的执行。它可以是按下键搜索查询,也可以是快速单击上一个或下一个按钮(否则如果连续快速单击将发送多个请求,并且最终不会使用)。它使用一个全局对象存储每次执行时间,并将其与最新的请求进行比较。

因此,结果是只有最后一个点击/动作将被实际调用,因为这些请求存储在队列中,如果队列中没有其他具有相同标签的请求,则在X毫秒后调用!

function delay_method(label,callback,time){
    if(typeof window.delayed_methods=="undefined"){window.delayed_methods={};}  
    delayed_methods[label]=Date.now();
    var t=delayed_methods[label];
    setTimeout(function(){ if(delayed_methods[label]!=t){return;}else{  delayed_methods[label]=""; callback();}}, time||500);
  }

您可以设置自己的延迟时间(可选,默认为500ms)。并以“闭包方式”发送函数参数。

例如,如果你想调用下面的函数:

function send_ajax(id){console.log(id);}

为了防止多个send_ajax请求,可以使用以下方法延迟它们:

Delay_method ("check date", function(){send_ajax(2);}, 600);

每个使用标签“check date”的请求只有在600毫秒的时间范围内没有其他请求时才会被触发。这个参数是可选的

标签独立性(调用相同的目标函数),但同时运行:

delay_method("check date parallel", function(){send_ajax(2);});
delay_method("check date", function(){send_ajax(2);});

导致调用相同的函数,但由于它们的标签不同而单独延迟它们

如果你想在类型完成后搜索,使用一个全局变量来保存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);  
}   

好吧,我也做了一段代码限制高频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 */ });
});

下面是我写的一个建议,它可以处理表单中的多个输入。

这个函数获取输入字段的Object,放到你的代码中

function fieldKeyup(obj){
    //  what you want this to do

} // fieldKeyup

这是实际的delayCall函数,负责多个输入字段

function delayCall(obj,ms,fn){
    return $(obj).each(function(){
    if ( typeof this.timer == 'undefined' ) {
       // Define an array to keep track of all fields needed delays
       // This is in order to make this a multiple delay handling     
          function
        this.timer = new Array();
    }
    var obj = this;
    if (this.timer[obj.id]){
        clearTimeout(this.timer[obj.id]);
        delete(this.timer[obj.id]);
    }

    this.timer[obj.id] = setTimeout(function(){
        fn(obj);}, ms);
    });
}; // delayCall

用法:

$("#username").on("keyup",function(){
    delayCall($(this),500,fieldKeyup);
});