11

我想在用户暂停输入时触发 ajax 操作(而不是在每次按键后)。所以我做了这样的事情:

当用户在空闲 3 秒后停止输入时,将执行功能完成......(它是 - 但为什么长短语要运行 3 次 - 我希望它只运行一次,因为我在每次按键后清除超时)。问题是什么 ?

var timer; 
var interval = 3000; 
$('#inp').keyup(function() {
  timer = setTimeout(done, interval); 
}); 

$('#inp').keydown(function() {
  clearTimeout(timer)  
}); 

function done() {
  console.log('ajax'); 
}

关于 jsfiddle 的工作示例:http: //jsfiddle.net/vtwVH/

4

5 回答 5

9

键入时,有时您可能会先按下另一个键,然后再松开第一个键。您可能不会注意到这一点,尤其是在您输入长短语时。在这种情况下,事件的顺序不是down up down upbut down down up up,因此将设置两个超时。

在设置超时之前(在同一个事件处理程序中)清除超时更加一致。

于 2013-02-01T13:01:57.980 回答
7

问题是您正在覆盖timerkeydown 事件中的变量。

因此,如果您在 Timout 被清除之前按下另一个键,例如继续按住一个键

对 timeOut 的引用丢失,您无法再次清除它。

要解决此问题,您可以在keyUp事件中清除并设置计时器,例如

var timer; 
var interval = 3000; 


$('#inp').keyup(function(e){ 
    if(timer) {
        clearTimeout(timer);
    }
    timer = setTimeout(done, interval); 

}); 

function done() {
    console.log('ajax'); 
}

这是一个工作小提琴

于 2013-02-01T13:08:07.603 回答
1

这些事件似乎没有遵循严格的顺序规则,第二个 keydown 比第一个 keyup 早,因此计时器被初始化多次。

试试这个模组:

$('#inp').keyup(function(){
  clearTimeout(timer);
  timer = setTimeout(done, interval); 
}); 
于 2013-02-01T13:04:52.553 回答
0

只要确保清除间隔:

var timer; 
var interval = 3000; 


$('#inp').keyup(function(){
  clearTimeout(timer)  
  timer = setTimeout(done, interval); 
}); 

$('#inp').keydown(function(){
  clearTimeout(timer)  
}); 

function done() {
  console.log('ajax'); 
}

JSFiddle

于 2013-02-01T13:03:26.560 回答
0

除非用户输入速度真的很慢,否则keydownandkeyup不会按照你想象的顺序出现。例如,您可以获取两个keydown事件,然后是两个keyup事件。如果你不处理,第二个keyup事件将启动另一个计时器并覆盖对第一个计时器的引用,这样它就不会被清除。

跟踪超时是否正在运行,keyup如果正在运行则将其清除:

var timer = null;
var interval = 3000; 
$('#inp').keyup(function(){
  if (timer != null) {
    window.clearTimeout(timer)  
  }
  timer = window.setTimeout(done, interval); 
}); 

$('#inp').keydown(function(){
  if (timer != null) {
    window.clearTimeout(timer);
    timer = null;
  }
}); 

function done() {
  timer = null;
  console.log('ajax'); 
}

演示:http: //jsfiddle.net/Guffa/vtwVH/3/

于 2013-02-01T13:11:04.120 回答