我的网页上有一个搜索框,其中包含复选框,以便用户过滤搜索结果。一次只能检查一个复选框。
单击复选框时,我的代码会运行并将过滤器应用于列表并返回正确的结果。
我遇到的问题是,当快速连续点击多次复选框时,它会将请求排队并逐个拉回。如果选中复选框,然后多次取消选中,则可能需要一段时间。
在Javascript中是否有任何方式通知函数它已被再次调用,它应该停止除了最后一个请求之外的所有内容?
答案 0 :(得分:17)
您希望将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);
为什么禁用click事件,将disabled属性添加到复选框而不仅仅是全局锁定变量?好吧,全局锁可能有些容易出错,但更重要的是,我们已经有了一个在DOM中很重要的全局对象。如果我们只修改DOM状态,我们会得到正确的行为,并向用户发出信号,告知他们应该在复选框上放松,直到搜索完成。
也就是说,使用任何类型的锁定/解除绑定方案来向用户指示加载微调器或您正在工作的东西可能是有意义的。
答案 1 :(得分:12)
您可以使用锁定模式:
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秒钟内释放锁定为止。
这种模式相当不错,因为它可以在您释放锁定时为您提供控制权,而不是依赖于“去抖动”等定时间隔。例如,它将与Ajax一起使用。如果您的复选框正在触发Ajax调用以进行过滤,您可以:
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;
});
}
答案 2 :(得分:4)
这里的问题是反复点击该复选框。您应该在处理时禁用复选框(这也会禁用元素上的click事件),然后在完成处理后重新启用复选框。
去抖是一个好主意,但你并不总是知道你的处理功能需要多长时间才能完成。
这是一个简单的例子,使用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);