我有一个复选框,可以切换某些行为,但如果有人连续100次点击,我不想向服务器端发送100个请求。
这就是我到目前为止所找到的(找到此代码片段):
deBouncer = function($,cf,of, interval){
var debounce = function (func, threshold, execAsap) {
var timeout;
return function debounced () {
var obj = this, args = arguments;
function delayed () {
if (!execAsap)
func.apply(obj, args);
timeout = null;
}
if (timeout)
clearTimeout(timeout);
else if (execAsap)
func.apply(obj, args);
timeout = setTimeout(delayed, threshold || interval);
}
}
jQuery.fn[cf] = function(fn){ return fn ? this.bind(of, debounce(fn)) : this.trigger(cf); };
};
在我的文档就绪功能中:
deBouncer(jQuery,'smartoggle', 'click', 1500);
然后事件本身:
$(window).smartoggle(function(e){
MyToggleFunction();
});
这是因为我将1500毫秒作为去抖动时段,所以如果你用1500毫秒点击n次,它将只向服务器发送最新状态。
然而,使用它有副作用,现在我的其他东西的点击事件搞砸了。我在这里做错了吗?是否有更好的去抖动方法?
答案 0 :(得分:11)
刚刚退出执行实际工作的功能,我不会为此加载整个库。
var debouncedSomeFunction = debounce(someFunction, 1500);
debouncedSomeFunction();
debouncedSomeFunction();
debouncedSomeFunction();
setTimeout(debouncedSomeFunction, 2000);
function debounce(fn, bufferInterval) {
var timeout;
return function () {
clearTimeout(timeout);
timeout = setTimeout(fn.apply.bind(fn, this, arguments), bufferInterval);
};
}
function someFunction() {
log('someFunction executed');
}
function log(text) {
document.body.appendChild(document.createTextNode(text));
document.body.appendChild(document.createElement('br'));
}
答案 1 :(得分:3)
不确定是否有适当的"这样做的方法。
说过下划线有这样一个实用程序会创建你的函数的去抖动版本......
var MyToggleDebounced = _.debounce(MyToggleFunction, 1500);
然后在点击处理程序中使用MyToggleDebounced
。
Link to debounce docs on underscorejs
看看带注释的来源,了解他们是如何做到的。
答案 2 :(得分:0)
我认为这个问题比起初看起来要好。关于Http Ajax请求如何工作有一个警告。如果您将延迟设置为1500毫秒,并且您可以保证在此时间范围内提供每个请求,则其他答案将正常工作。但是,如果任何请求变得非常慢,那么请求可能会出现故障。如果发生这种情况,最后处理的请求是显示数据的请求,而不是最后发送的请求。
我写这个类是为了避免这个警告(在Typescript中,但你应该能够阅读它):
export class AjaxSync {
private isLoading: boolean = false;
private pendingCallback: Function;
private timeout;
public debounce(time: number, callback: Function): Function {
return this.wrapInTimeout(
time,
() => {
if (this.isLoading) {
this.pendingCallback = callback;
return;
}
this.isLoading = true;
callback()
.then(() => {
this.isLoading = false;
if (this.pendingCallback) {
const pendingCallback = this.pendingCallback;
this.pendingCallback = null;
this.debounce(time, pendingCallback);
}
});
}
);
}
private wrapInTimeout(time, callback) {
return () => {
clearTimeout(this.timeout);
this.timeout = setTimeout(callback, time);
};
}
}
这将阻止同时处理两个ajax请求,如果有一个请求,这将发送另一个请求。