可以jQuery的deferreds被取消?jQuery、deferreds

2023-09-11 00:48:38 作者:盏茶作酒

我有一个情况我想取消一个延期。该延迟与Ajax调用相关联。

I have a situation where I want to cancel a deferred. The deferred is associated with an ajax call.

我不使用由$就恢复正常XHR对象。我使用JSONP,这意味着我不能使用HTTP状态codeS的错误处理,并有嵌入他们的反应。的codeS是然后检查和相关联的延迟对象被标记为已解决或相应拒绝。我有一个自定义的API函数,它为我。

I don't use the normal xhr objects returned by $.ajax. I'm using jsonp, which means I can't use HTTP status codes for error handling and have to embed them in the responses. The codes are then examined and an associated deferred object is marked as resolved or rejected accordingly. I have a custom api function that does this for me.

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;
}

为什么要取消递延

有一个输入字段,充当列表的过滤器,将输入结束后自动更新列表半秒钟。因为可能有两个Ajax调用是优秀的时间,我需要取消previous调用,以确保它不会之后的第二回,并显示旧数据。

Why I want to cancel the deferred

There is an input field that serves as a filter for a list and will automatically update the list half a second after typing ends. Because it is possible for two ajax calls to be outstanding at a time, I need to cancel the previous call to make sure that it doesn't return after the second and show old data.

我不想拒绝延期,因为这将触发附 .fail处理程序()。 在我不能忽视它,因为它会自动被标记为已解决或拒绝了阿贾克斯的回报的时候。 删除递延当Ajax调用返回,并试图以纪念延迟为已解决或拒绝将导致一个错误。 I don't want to reject the deferred because that will fire handlers attached with .fail(). I can't ignore it because it will automatically be marked as resolved or rejected when the ajax returns. Deleting the deferred will cause an error when the ajax call returns and tries to mark the deferred as resolved or rejected.

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

Is there a way to cancel the deferred or remove any attached handlers?

在如何解决我的设计建议是值得欢迎的,但preference将给予寻找一种方法来或prevent他们射击删除处理。

Advice on how to fix my design is welcome, but preference will be given to finding a way to remove handlers or prevent them from firing.

推荐答案

展望jQuery的doc和code,我看不出有什么办法可以取消一个jQuery推迟。

Looking in the jQuery doc and code, I don't see any way to cancel a jQuery deferred.

相反,你可能需要一种方法在你的 resolveWith 处理知道后续的Ajax调用已经被解雇,这Ajax调用应该忽略它的结果。你可以做到这一点与全球递增计数器。在你的Ajax调用的开始,你增加计数器,然后你抢值到一个局部变量或把它作为Ajax对象上的属性。在你的 resolveWith 处理程序中,检查是否计数器仍具有相同的值,当你的Ajax调用启动。如果没有,你忽略的结果。如果是这样,没有新的Ajax调用已经被解雇,因此您可以处理结果。

Instead, you probably need a way in your resolveWith handler to know that a subsequent ajax call has already been fired and this ajax call should ignore its result. You could do that with a globally incrementing counter. At the start of your ajax call, you increment the counter and then you grab the value into a local variable or put it as a property on the ajax object. In your resolveWith handler, you check to see if the counter still has the same value as when your ajax call started. If not, you ignore the result. If it does, no new ajax calls have been fired so you can process the result.

另外,你可以拒绝触发一个新的Ajax调用,而一个是在飞行已​​经让你永远在同一时间有一个以上的飞行。当一个完成后,您既可以只使用结果,或者如果需要触发下一个。

Alternately, you could refuse to fire a new ajax call while one is in flight already so you never had more than one in flight at a time. When the one finishes, you could either just use that result or fire the next one if desired.