JavaScript超时触发3次而不是一次(clearTimeout不起作用?)

时间:2013-02-01 12:58:59

标签: javascript jquery

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

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

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/

5 个答案:

答案 0 :(得分:9)

键入时,有时可能会在释放第一个键之前按下另一个键。你可能没有注意到这一点,特别是如果你输入一个长短语。在这种情况下,事件的顺序不是down up down up而是down down up up,因此将设置两个超时。

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

答案 1 :(得分:7)

问题是你正在覆盖你的keydown事件中的timer变量。

因此,如果您在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'); 
}

继承人工作fiddle

答案 2 :(得分:1)

事件似乎不遵循严格的顺序规则,第二个keydown比第一个keyup早,所以计时器多次初始化。

试试这个mod:

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

答案 3 :(得分: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

答案 4 :(得分:0)

除非用户输入的速度非常慢,否则keydownkeyup将不会按您认为的顺序排列。例如,您可以获得两个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/