最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

jquery - JavaScript timeout fires 3 times instead of once (clearTimeout is not working ?) - Stack Overflow

programmeradmin1浏览0评论

I want to fire an ajax action when user make a pause in typing (instead of after every keypressed). So I made something like this:

When the user stops typing after 3 secs of being idle function done is to be executed ... (it is - but why 3 times for long phrases - I would expect it to run only once since I clear timeout after every keydown). What is the problem ?

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

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

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

Working example on jsfiddle : /

I want to fire an ajax action when user make a pause in typing (instead of after every keypressed). So I made something like this:

When the user stops typing after 3 secs of being idle function done is to be executed ... (it is - but why 3 times for long phrases - I would expect it to run only once since I clear timeout after every keydown). What is the problem ?

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

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

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

Working example on jsfiddle : http://jsfiddle.net/vtwVH/

Share Improve this question edited Feb 1, 2013 at 13:12 David G 96.8k41 gold badges172 silver badges257 bronze badges asked Feb 1, 2013 at 12:58 user1983515user1983515 3451 silver badge6 bronze badges 1
  • 1 stackoverflow.com/questions/1909441/jquery-keyup-delay – Nishant Jani Commented Feb 1, 2013 at 13:13
Add a comment  | 

5 Answers 5

Reset to default 9

When you type, you may sometimes press down another key before releasing the first. You may not notice this, particularly if you're typing a long phrase. In that case, the order of events is not down up down up but down down up up, and so two timeouts will be set.

It is more consistent to clear the timeout just before setting it (in the same event handler).

The Problem is you are overwriting the timer variable in your keydown event.

So if you press another key before the Timout gets cleared e.g keep holding a key

The reference to the timeOut is lost and you cannot clear it again.

To fix this you could just clear and set the Timer in the keyUp event like

var timer; 
var interval = 3000; 


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

}); 

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

Heres a working fiddle

The events seem to not follow strict sequential rules, second keydown comes earlier than first keyup, so the timer gets initialized multiple times.

Try this mod:

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

Just make sure you clear the interval:

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

Unless the user types really slow, the keydown and keyup won't come in the order that you think. You can for example get two keydown events followed by two keyup events. If you don't handle that, the second keyup event will start another timer and overwrite the reference to the first timer so that it won't be cleared.

Keep track of whether the timeout is running, and clear it in keyup if it is running:

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'); 
}

Demo: http://jsfiddle.net/Guffa/vtwVH/3/

发布评论

评论列表(0)

  1. 暂无评论