【问题标题】:JavaScript timeout fires 3 times instead of once (clearTimeout is not working ?)JavaScript 超时触发 3 次而不是一次(clearTimeout 不起作用?)
【发布时间】:2013-02-01 12:58:58
【问题描述】:

我想在用户暂停输入时触发 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/

【问题讨论】:

标签: javascript jquery


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    问题是您在 keydown 事件中覆盖了 timer 变量。

    所以如果你在超时被清除之前按下另一个键例如继续按住一个键

    对 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

    【讨论】:

      【解决方案3】:

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

      试试这个模组:

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

      【讨论】:

        【解决方案4】:

        只要确保你清除了间隔:

        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

        【讨论】:

          【解决方案5】:

          除非用户输入速度很慢,否则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/

          【讨论】:

            猜你喜欢
            • 2011-01-12
            • 1970-01-01
            • 1970-01-01
            • 2022-01-04
            • 1970-01-01
            • 2016-04-21
            • 1970-01-01
            • 2022-01-25
            相关资源
            最近更新 更多