可以取消jQuery延期吗?

39 javascript ajax jquery cancellation jquery-deferred

我有一种情况,我想取消延期.延迟与ajax调用相关联.

为什么我使用延期

我不使用$ .ajax返回的普通xhr对象.我正在使用jsonp,这意味着我无法使用HTTP状态代码进行错误处理,并且必须将它们嵌入到响应中.然后检查代码,并相应地将关联的延迟对象标记为已解决或拒绝.我有一个自定义api函数,为我这样做.

function api(options) {
  var url = settings('api') + options.url;
  var deferred = $.Deferred(function(){
    this.done(options.success);
    this.fail(options.error);
  });
  $.ajax({
    'url': url,
    'dataType':'jsonp',
    'data': (options.noAuth == true) ? options.data : $.extend(true, getAPICredentials(), options.data)
  }).success(function(jsonReturn){
    // Success
    if(hasStatus(jsonReturn, 'code', 200)) {
      deferred.resolveWith(this, [jsonReturn]);
    } 
    // Failure
    else {
      deferred.rejectWith(this, [jsonReturn]);
    }
  });

  return deferred;
}
Run Code Online (Sandbox Code Playgroud)

为什么我要取消延期

有一个输入字段用作列表的过滤器,并在键入结束后半秒自动更新列表.因为一次可能有两个ajax调用是未完成的,所以我需要取消之前的调用以确保它在第二个调用之后不返回并显示旧数据.

解决方案我不喜欢

  • 我不想拒绝延期,因为这将解雇附带的处理程序.fail().
  • 我不能忽略它,因为它会在ajax返回时自动标记为已解决或被拒绝.
  • 删除延迟将在ajax调用返回时导致错误,并尝试将延迟标记为已解决或已拒绝.

我该怎么办?

有没有办法取消延期或删除任何附加的处理程序?

有关如何修复我的设计的建议值得欢迎,但我们会优先考虑找到一种方法来删除处理程序或防止它们被触发.

jfr*_*d00 15

查看jQuery文档和代码,我没有看到任何取消jQuery延迟的方法.

相反,您可能需要在resolveWith处理程序中知道已经触发了后续的ajax调用,并且此ajax调用应该忽略其结果.您可以使用全局递增计数器来完成此操作.在ajax调用开始时,您递增计数器,然后将值捕获到局部变量中或将其作为属性放在ajax对象上.在您的resolveWith处理程序中,您检查计数器是否仍具有与ajax调用开始时相同的值.如果没有,则忽略结果.如果是,则不会触发新的ajax调用,因此您可以处理结果.

或者,你可以拒绝在一个人在飞行途中发起一个新的ajax呼叫,这样你一次就不会有一个以上的飞行.完成后,您可以根据需要使用该结果或触发下一个结果.

  • 我最好选择`rejectWith`,但这个想法是+1 (3认同)

Rya*_*n Q 6

虽然你不能像你想要的那样"取消"延迟,你可以创建一个简单的闭包来跟踪最后一个ajax调用,通过$ .ajax返回一个jqXHR对象.通过执行此操作,您可以简单地中止()当新的jqXHR进入时播放,如果最后一个未完成.在你的代码的情况下,它将拒绝jqXHR并保留deferred open以便按照你最初的需要删除.

var api = (function() {
    var jqXHR = null;

    return function(options) {
        var url = options.url;

        if (jqXHR && jqXHR.state() === 'pending') {
            //Calls any error / fail callbacks of jqXHR
            jqXHR.abort();
        }

        var deferred = $.Deferred(function() {
            this.done(options.success);
            this.fail(options.error);
        });

        jqXHR = $.ajax({
             url: url,
             data: options.toSend,
             dataType: 'jsonp'
        });

        jqXHR.done(function(data, textStatus, jqXHR) {
            if (data.f && data.f !== "false") {
                deferred.resolve();
            } else {
                deferred.reject();
            }
        });

        //http://api.jquery.com/deferred.promise/  
        //keeps deferred's state from being changed outside this scope      
        return deferred.promise();
    };
})();
Run Code Online (Sandbox Code Playgroud)

我已经在jsfiddle发布了这个.如果你想测试它.设置超时与jsfiddles delayer结合使用,以模拟正在中断的呼叫.您需要启用控制台的浏览器才能查看日志.

在旁注上,将任何.success(),. error()和complete()方法切换为延迟方法done(),fail()和always().通过jquery/ajax

弃用注意:jQuery 1.8中不推荐使用jqXHR.success(),jqXHR.error()和jqXHR.complete()回调.要准备最终删除的代码,请使用jqXHR.done(),jqXHR.fail()和jqXHR.always()作为更新的代码

  • 感谢Artur的领导.有必要提一下为什么OP不能用于编辑或提出改变建议. (3认同)