JavaScript/jQuery - 为按钮添加防抖功能

13
我想在按钮上添加防抖动功能,但我希望每次用户点击按钮时都执行一些操作,但只有在用户按下按钮后5秒钟后才执行SQL更新。通常情况下,节流似乎直接应用于监听器。在这里,我希望每次单击按钮时执行一些操作,然后在合理的等待时间后进行更新。
我不确定如何在这种情况下使用函数...
参考:http://code.google.com/p/jquery-debounce/
$('#myButton').click(function() {
    // do a date calculation
    // show user changes to screen
    // wait until user has has stopped clicking the 
             // button for 5 seconds, then update file with "process" function.

});

function process(){
    // update database table
}

防抖函数语法

$('input').bind('keyup blur', $.debounce(process, 5000));

你不知道$.debounce是如何工作的吗?还是你遇到了什么问题?编辑:啊,我明白了... - Felix Kling
我已经添加了有关我的问题的详细信息。 防抖和节流是ajax中经常使用的模式。 这里有一些不错的阅读材料... http://ajaxpatterns.org/Submission_Throttling - george
5个回答

23

你仍然可以这样使用$.debounce

// create new scope
(function() {
     // create debounced function
     var dprocess = $.debounce(process, 5000);

     // bind event handler
     $('#myButton').click(function() {
         // do a date calculation
         // show user changes to screen
         // call the function
         dprocess();
     });
}());

没有使用 $.debounce 的替代方法(您可以始终以此方式防抖动您的代码,而无需使用jQuery):

// create new scope
(function() {
     var timer;

     // bind event handler
     $('#myButton').click(function() {
         if(timer) {
             clearTimeout(timer);
         }
         // do a date calculation
         // show user changes to screen
         // call the function
         timer = setTimeout(process, 5000);
     });
}());

这看起来像是正确的方向。你是在匿名函数中包装进程吗?当调用时,dprocess()会在作用域内吗? - george
你的意思是它是否可以从点击事件处理程序中访问到吗?是的。我添加了立即函数调用,以便 dprocess 不会泄漏到全局范围。当然,如果你的代码已经在一个 ready 事件处理程序中,你可以删除这个调用。 - Felix Kling
1
非常好的无需jQuery的防抖示例。它几乎可以消除对jQuery的需求。几乎... - Cerin

14

使用原生/纯JS和jquery/underscore.js实现防抖。

示例

JS

//Native/Vanilla JS
document.getElementById('dvClickMe').onclick = debounce(function(){
    alert('clicked - native debounce'); 
}, 250);


function debounce(fun, mil){
    var timer; 
    return function(){
        clearTimeout(timer); 
        timer = setTimeout(function(){
            fun(); 
        }, mil); 
    };
}

//jQuery/Underscore.js
$('#dvClickMe2').click(_.debounce(function(){
    alert('clicked - framework debounce'); 
}, 250)); 

HTML

<div id='dvClickMe'>Click me fast! Native</div>
<div id='dvClickMe2'>Click me fast! jQuery + Underscore</div>

4
 var timer;
 $('#myButton').click(function() {
     //Called every time #myButton is clicked         
     if(timer) clearTimeout(timer);
     timer = setTimeout(process, 5000);
 });

function process(){
  //Called 5000ms after #myButton was last clicked 
}

0

如果使用去抖函数来去抖多个函数,使用全局变量可能不是最佳解决方案。为此,我们应该将计时器限定在被去抖函数的范围内。

function debounce(func, timeout = 2000) {
  if (func.timer) clearTimeout(func.timer);
  func.timer = setTimeout(func, timeout);
}

debounce(func1, 4000);
debounce(func2, 1000);

注意:这不能与匿名函数一起使用;


-4
为什么不直接使用 setTimeOut(function() { process(); }, 5000);

据我所知,这只是增加了一个延迟时间。我想要忽略最初的点击,然后当用户静止几秒钟后再运行更新。 - george
可以,你也可以在没有防抖的情况下实现相似的功能,但是使用防抖可能是更好的选择。 - jzila

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接