我绑定了一个 keyup
事件到一个需要大约四分之一秒才能完成的函数。
$("#search").keyup(function() {
//code that takes a little bit to complete
});
当用户输入完整的单词或快速按键时,该函数将被连续调用多次,并且需要一段时间才能完成所有调用。是否有一种方法可以限制事件调用的频率,以便如果有多个事件在短时间内触发,它只会触发最近调用的一个?
我绑定了一个 keyup
事件到一个需要大约四分之一秒才能完成的函数。
$("#search").keyup(function() {
//code that takes a little bit to complete
});
当用户输入完整的单词或快速按键时,该函数将被连续调用多次,并且需要一段时间才能完成所有调用。看一下jQuery Debounce。
$('#search').keyup($.debounce(function() {
// Will only execute 300ms after the last keypress.
}, 300));
.sel1, .sel2 sel3
时,这个不起作用。 - HungryCoder这里有一个潜在的解决方案,不需要插件。使用一个布尔值来决定是否执行keyup回调函数,或者跳过它。
var doingKeyup = false;
$('input').keyup(function(){
if(!doingKeyup){
doingKeyup=true;
// slow process happens here
doingKeyup=false;
}
});
setTimeout
/ clearTimeout
进行包装。 - josh3736// slow process
发生在另一个事件循环中时,这才是正确的方式。否则,由于JS是单线程的,这是没有用的。 - Ashish Negi您还可以使用优秀的Underscore/_库。
在目前最受欢迎的Josh的答案中,评论中存在争议,是否真的需要限制调用次数,或者你想要一个去抖动器。区别有点微妙,但Underscore都有:_.debounce(function, wait, [immediate])
和_.throttle(function, wait, [options])
。
如果您还没有使用Underscore,请尝试一下。它可以使您的JavaScript代码更加简洁,并且足够轻便,足以让大多数库反对者停下来思考。
/* delayed onchange while typing jquery for text boxes widget
usage:
$("#SearchCriteria").delayedChange(function () {
DoMyAjaxSearch();
});
*/
(function ($) {
$.fn.delayedChange = function (options) {
var timer;
var o;
if (jQuery.isFunction(options)) {
o = { onChange: options };
}
else
o = options;
o = $.extend({}, $.fn.delayedChange.defaultOptions, o);
return this.each(function () {
var element = $(this);
element.keyup(function () {
clearTimeout(timer);
timer = setTimeout(function () {
var newVal = element.val();
newVal = $.trim(newVal);
if (element.delayedChange.oldVal != newVal) {
element.delayedChange.oldVal = newVal;
o.onChange.call(this);
}
}, o.delay);
});
});
};
$.fn.delayedChange.defaultOptions = {
delay: 1000,
onChange: function () { }
}
$.fn.delayedChange.oldVal = "";
})(jQuery);
两种简单的限流方法的通用实现。(我更喜欢通过这些简单的函数来实现,而不是添加另一个jquery插件)
在最后一次调用后等待一段时间
当用户持续输入查询时,这个方法非常有用,我们不想每次都调用搜索功能。
function throttle(time, func) {
if (!time || typeof time !== "number" || time < 0) {
return func;
}
var throttleTimer = 0;
return function() {
var args = arguments;
clearTimeout(throttleTimer);
throttleTimer = setTimeout(function() {
func.apply(null, args);
}, time);
}
}
不超过给定时间调用给定函数
以下内容对于清除日志非常有用
function throttleInterval(time, func) {
if (!time || typeof time !== "number" || time < 0) {
return func;
}
var throttleTimer = null;
var lastState = null;
var eventCounter = 0;
var args = [];
return function() {
args = arguments;
eventCounter++;
if (!throttleTimer) {
throttleTimer = setInterval(function() {
if (eventCounter == lastState) {
clearInterval(throttleTimer);
throttleTimer = null;
return;
}
lastState = eventCounter;
func.apply(null, args);
}, time);
}
}
}
使用非常简单:
在输入框最后一次按键后等待2秒,然后调用应该被节流的函数。
$("#inputBox").on("input", throttle(2000, function(evt) {
myFunctionToThrottle(evt);
}));
我在审查zurb-foundation的更改时遇到了这个问题。他们添加了自己的方法用于防抖和节流。看起来这可能与@josh3736在他的答案中提到的jquery-debounce相同。
从他们的网站上得知:
// Debounced button click handler
$('.button').on('click', Foundation.utils.debounce(function(e){
// Handle Click
}, 300, true));
// Throttled resize function
$(document).on('resize', Foundation.utils.throttle(function(e){
// Do responsive stuff
}, 300));
对于快速解决问题(注意咖啡脚本),以下代码似乎是最简单的选择(无需外部库):
running = false
$(document).on 'keyup', '.some-class', (e) ->
return if running
running = true
$.ajax
type: 'POST',
url: $(this).data('url'),
data: $(this).parents('form').serialize(),
dataType: 'script',
success: (data) ->
running = false