【问题标题】:How to kill a Javascript function if it is called again?如果再次调用 Javascript 函数,如何杀死它?
【发布时间】:2014-09-26 23:24:33
【问题描述】:

我的网页上有一个带有复选框的搜索框,以便用户过滤他们的结果。一次只能选中一个复选框。

单击复选框时,我的代码会运行并将过滤器应用于列表并返回正确的结果。

我遇到的问题是,当一个复选框被快速连续多次单击时,它会将请求排队并将它们一个一个拉回来。如果选中一个复选框然后多次取消选中,这可能需要一段时间。

在 Javascript 中有什么方法可以通知函数它已被再次调用并且它应该停止除最后一个请求之外的所有内容?

【问题讨论】:

  • 如果“一次只能选中一个复选框。”你应该使用单选按钮而不是复选框
  • 为什么在执行检查时不设置一个变量?
  • 能否禁用 onclick 处理程序中的复选框,然后在 ajax 调用返回时重新启用它?
  • @Lloyd 添加无过滤单选按钮选项?

标签: javascript function terminate debouncing


【解决方案1】:

这里的问题是复选框被反复点击。您应该在处理时禁用您的复选框(这也会禁用元素上的点击事件),然后在完成处理后重新启用您的复选框。

去抖动是个好主意,但您并不总是知道处理函数需要多长时间才能完成。

这是一个简单的例子,使用 jquery promise 在一些处理后重新启用复选框 http://jsfiddle.net/94coc8sd/

使用以下代码:

function processStuff() {
    var dfd = $.Deferred();

    // do some processing, when finished, 
    // resolve the deferred object
    window.setTimeout(function(){
        dfd.resolve();
    }, 2000);

    return dfd.promise();
}

function startProcessing() {
    $('#processingCheckbox').attr('disabled', 'disabled');
     var promise = processStuff();    
    promise.done(enableCheckbox);
}

function enableCheckbox() {
    $('#processingCheckbox').removeAttr('disabled');
}

$('#processingCheckbox').on('click', startProcessing);

【讨论】:

  • 是的,去抖动更适合处理按键事件(键入时自动完成/搜索)用例。
【解决方案2】:

您想将onclick 回调包装在一个去抖函数中,例如

http://underscorejs.org/#debounce

说你有这个

function search() {
    // ...
}

$jquery(".myFilterCheckboxes").click(search);

您应该能够将以上内容更改为:

// Only allow one click event / search every 500ms:
$jquery(".myFilterCheckboxes").click(_.debounce(search, 500));

那里有大量的去抖动函数,如果你不能或不想包含 underscore.js,那么编写自己的函数真的没什么大不了的。

我的第一个想法是去抖动,因为您提到多次点击会在短时间内创建多个事件。去抖动通常用于诸如预先输入搜索或自动完成之类的事情,以便在按键之间留出一点空间来思考时间。

正如其他人所提到的,在搜索运行时简单地禁用复选框/单击事件可能更有意义。在这种情况下,请尝试以下操作:

function disableClick(elem) {
  elem.unbind("click");
  elem.attr("disabled", true);
}

function enableClick(elem, onclick) {
  // Enable click events again
  elem.live("click", search);
  // Enable the checkboxes
  elem.removeAttr("disabled");
}

function search() {
  var boxes = $jquery(".myFilterCheckboxes");
  disableClick(boxes);
  $.get(...).always(function() {
    enableClick(boxes, search);
  });
}

$jquery(".myFilterCheckboxes").live("click", search);

为什么要禁用点击事件,将禁用属性添加到复选框而不仅仅是全局锁定变量?好吧,全局锁可能有点容易出错,但更重要的是,我们已经有了一个在 DOM 中很重要的全局对象。如果我们只是修改 DOM 状态,我们会得到正确的行为并向我们的用户发出信号,他们应该在复选框上放松一下,直到搜索完成。

也就是说,对于任何类型的锁定/解除绑定场景,通过加载微调器或您正在做的事情向用户指示可能都是有意义的。

【讨论】:

  • 完美满足我的要求,感谢您的回答。我什至不知道去抖动这个词。再次感谢
  • 在这种情况下,我认为您应该为立即参数传递 true 以导致 debounce 在等待间隔的前沿而不是后沿触发函数。否则会有延迟。
【解决方案3】:

您可以使用锁定模式:

http://jsfiddle.net/RU6gL/

HTML

<input type="checkbox" onclick="fire()" >CB1
<br />
<input type="checkbox" onclick="fire()" >CB2

JS

function_lock = false

fire = function() {
    // First, check the lock isn't already reserved. If it is, leave immediately.
    if (function_lock) return;

    // We got past the lock check, so immediately lock the function to 
    // stop others entering
    function_lock = true;

    console.log("This message will appear once, until the lock is released")

    // Do your work. I use a simple Timeout. It could be an Ajax call.
    window.setTimeout(function() {
        // When the work finishes (eg Ajax onSuccess), release the lock.
        function_lock = false;
    }, 2000);
}

在本例中,无论复选框被点击多少次,该函数只会运行一次,直到超时2秒后释放锁。

这种模式非常好,因为它可以让你在释放锁时控制 opver,而不是依赖像“去抖动”这样的定时间隔。例如,它将与 Ajax 一起使用。如果您的复选框触发了 Ajax 调用来进行过滤,您可以:

  1. 第一次点击时,设置锁定
  2. 调用 Ajax 端点。后续点击不会调用 Ajax 端点。
  3. 在 Ajax 成功函数中,重置锁。
  4. 现在可以再次单击复选框。

HTML

<input type="checkbox" onclick="doAjax()" >CB2

JS

ajax_lock = false

doAjax: function() {
    // Check the lock.
    if (ajax_lock) return;

    // Acquire the lock.
    ajax_lock = true;

    // Do the work.
    $.get("url to ajax endpoint", function() {
         // This is the success function: release the lock
         ajax_lock = false;
    });   
} 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-09
    • 2018-04-07
    相关资源
    最近更新 更多