使用jQuery中止JSONP ajax请求

时间:2011-06-24 18:58:48

标签: jquery ajax callback jsonp abort

我正在使用JSONP ajax调用来加载来自不同域的一些内容,如果用户在按钮上导致“鼠标悬停”,则执行所有这些操作。

我可以将$ .ajax()调用返回捕获为xhr对象,并在每次用户导致“鼠标悬停”时使用它来中止ajax请求。但是JSONP回调函数仍然被调用,这会导致错误,我认为这是因为xhr.abort()方法不会阻止调用回调函数。

我尝试使用try {} catch(e){}围绕$ .ajax()调用,但在调用xhr.abort()方法后,错误仍在继续。

有没有办法处理该异常?

引发的异常是这样的(根据Firebug): jQuery16102234208755205157_1308941669256不是功能

异常的内部结构如下: jQuery16102234208755205157_1308941669256({...来自其他域的我的json数据....})

5 个答案:

答案 0 :(得分:11)

基本答案就是here给出的答案:你不能真正abort()一个JSONP电话。所以真正的问题是,你如何避免多余的回调调用和你看到的错误?

你不能在回调周围使用try...catch,因为它是异步的;你必须从jQuery的结尾捕获它,而jQuery通常不处理从回调引发的异常。 (我在我的书中讨论了这个问题,Async JavaScript。)你要做的是为每个Ajax调用使用唯一的标识符,并且在调用成功回调时,检查该标识符是否与它时的标识符相同你打了电话。这是一个简单的实现:

var requestCount = 0;
$.ajax(url, {
  dataType: 'jsonp',
  requestCount: ++requestCount,
  success: function(response, code) {
    if (requestCount !== this.requestCount) return;
    // if we're still here, this is the latest request...
  }
});

我在这里利用了这样一个事实:传递给$.ajax的任何内容都附加到回调中用作this的对象。

如果jQuery让abort()为我们做这件事当然很好。

答案 1 :(得分:1)

jsonpString会覆盖jsonp请求中的回调函数名称。在'callback =?'中将使用此值代替'callback' URL中查询字符串的一部分。

因此{jsonp:'onJSONPLoad'}会导致'onJSONPLoad=?'传递给服务器。从jQuery 1.5开始,将jsonp选项设置为false可防止jQuery将?callback字符串添加到URL或尝试使用=?进行转换。在这种情况下,您还应该明确设置jsonpCallback设置。例如,{ jsonp: false, jsonpCallback: "callbackName" }

http://api.jquery.com/jQuery.ajax/

jQuery添加?callback=jQuery17109492628197185695_1339420031913并稍后将请求数据设置为此回调的参数,因此您将拥有:

jQuery17109492628197185695_1339420031913({
  "status": 200,
  "data": {your json}
})

为避免设置其他参数来请求URL并调用回调,请将此参数添加到ajax方法:jsonp:false,因此它将如下所示:

$.ajax({
  ...
  jsonp:false,
  ...
});

答案 2 :(得分:1)

请勿中止请求

只需存储$.ajax()

返回的 jqXHR 对象的某处
theJqXHR = $.ajax(....

如果用户取消请求,则保存已保存的对象

// user canceled
theJqXHR = null;

最后,当您收到响应(success回调)时,回调会将响应的jqXHR对象与保存的对象进行比较。

function successCallback(data, textStatus, jqXHR )
{
    if( theJqXHR !== jqXHR )
    {
        // user canceled; discard the response
        return;
    }

    // process the response
}

没有jQuery错误。

一般建议不要依赖abort(),即使是常规的ajax请求。

  1. 在任何情况下,您都不会在服务器上保存资源,因为您处理的请求将被处理,而且无法阻止。并会有回复。

  2. 某些(较旧的)浏览器无法正确处理abort()

  3. 只是" 缓存" jqXHR对象并自己处理 CANCEL 场景。

答案 3 :(得分:0)

Trevor Burnham的答案非常好,但您应该只是将请求与XHR参数进行比较,而不是跟踪请求计数;

doRequest: function() {
    this._freeRequest();

    this._request = $.getJSON(url + params + '&callback=?', function(response, status, xhr) {
        if (this._request !== xhr) return; // aborted

        // success
    }.bind(this)).done(this._freeRequest.bind(this));
}

_freeRequest: function() {
    if (this._request) {
        delete this._request;
    }
}

在上一个请求完成之前再次拨打doRequest_freeRequest,将导致"堕胎"通过使if (this._request !== xhr)行变为真,所述请求的结果为真,因为this._request将被删除或完全是另一个请求。

答案 4 :(得分:-3)

在jQuery 1.5中,所有Ajax API都有一个围绕本机XHR对象的包装器对象。看看:

http://api.jquery.com/jQuery.ajax/#jqXHR

 jqxhr.abort(); // should be what you're looking for