如何正确地去除ajax请求

时间:2014-05-06 11:41:17

标签: javascript jquery ajax

我有一个复选框,可以切换某些行为,但如果有人连续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次,它将只向服务器发送最新状态。

然而,使用它有副作用,现在我的其他东西的点击事件搞砸了。我在这里做错了吗?是否有更好的去抖动方法?

3 个答案:

答案 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请求,如果有一个请求,这将发送另一个请求。