使用jQuery中止JSONP ajax请求

时间:2022-12-06 21:19:00

I'm using a JSONP ajax call to load some content from a different domain, and all this stuff is executed if the user causes a "mouseover" on a button.

我使用JSONP ajax调用从不同的域加载一些内容,如果用户在一个按钮上造成一个“mouseover”,那么所有这些内容都将被执行。

I can capture the $.ajax() call return as a xhr object, and use it to abort the ajax request each time the user causes a "mouseover". But the JSONP callback function still gets called, and this causes an error, and I think it is beacuse the xhr.abort() method does not prevent the callback function to be called.

我可以捕获$.ajax()调用return作为xhr对象,并使用它在每次用户创建“mouseover”时中止ajax请求。但是JSONP回调函数仍然被调用,这导致了一个错误,我认为是beacuse xhr.abort()方法没有阻止调用回调函数。

I've tried surrounding the $.ajax() call with try{}catch(e){}, but after I call the xhr.abort() method, the error continues.

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

Is there a way to handle that exception?

有什么方法可以处理这个异常吗?

The raised exception is like this (according to Firebug): jQuery16102234208755205157_1308941669256 is not a function

引发的异常如下(根据Firebug): jQuery16102234208755205157_1308941669256不是函数

And the exception's internal structure is like this: jQuery16102234208755205157_1308941669256({... my json data from a different domain....})

异常的内部结构如下:jQuery16102234208755205157_1308941669256(我的json数据从不同的领域.... })

5 个解决方案

#1


-2  

In jQuery 1.5 all the Ajax APIs have a wrapper object around the native XHR objects. Take a look at:

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

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

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

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

#2


11  

The basic answer is simply the one given here: You can't really abort() a JSONP call. So the real question is, how do you avoid both superfluous callback invocations and the error you're seeing?

基本的答案就是这里给出的答案:您不能真正中止JSONP调用。所以真正的问题是,如何避免多余的回调调用和所看到的错误?

You can't use try...catch around the callback because it's asynchronous; you'd have to catch it from jQuery's end, and jQuery generally doesn't handle exceptions thrown from callbacks. (I discuss this in my book, Async JavaScript.) What you want to do instead is use a unique identifier for each Ajax call and, when the success callback is invoked, check whether that identifier is the same as it was when you made the call. Here's an easy implementation:

你不能用……捕获回调,因为它是异步的;您必须从jQuery端捕获它,而且jQuery通常不处理从回调抛出的异常。(我在《异步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...
  }
});

Here I'm taking advantage of the fact that anything you pass to $.ajax is attached to the object that's used as this in the callback.

这里我利用的是,任何东西都变成了$ajax附加到回调中使用的对象。

It'd be nice if jQuery made abort() do this for us, of course.

当然,如果jQuery让abort()为我们做这个就好了。

#3


1  

jsonpString overrides the callback function name in a jsonp request. This value will be used instead of 'callback' in the 'callback=?' part of the query string in the URL.

jsonpString重写jsonp请求中的回调函数名。这个值将在“callback=?”中使用,而不是“callback”。URL中查询字符串的一部分。

So {jsonp:'onJSONPLoad'} would result in 'onJSONPLoad=?' passed to the server. As of jQuery 1.5, setting the jsonp option to false prevents jQuery from adding the ?callback string to the URL or attempting to use =? for transformation. In this case, you should also explicitly set the jsonpCallback setting. For example, { jsonp: false, jsonpCallback: "callbackName" }

所以{jsonp:'onJSONPLoad'}会导致'onJSONPLoad=?传递到服务器。对于jQuery 1.5,将jsonp选项设置为false可以防止jQuery向URL添加?回调字符串或尝试使用=?为转换。在本例中,还应该显式地设置jsonpCallback设置。例如,{jsonp: false, jsonpCallback:“callbackName”}

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

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

jQuery adds ?callback=jQuery17109492628197185695_1339420031913 and later sets the request data as parameter to this callback, so you will have:

jQuery添加?callback=jQuery17109492628197185695_1339420031913,然后将请求数据作为这个回调的参数,

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

To avoid setting additional parameters to request a URL and calling callback, add this parameter to ajax method: jsonp:false, so it will be look like:

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

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

#4


1  

Do not abort the request

不要中止请求

Just store somewhere the XHR object

只需存储XHR对象的某个位置

theXHR = $.ajax(....

If the user cancel the request null the saved object

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

// user canceled
theXHR = null;

Finally when you receive the response (success callback) the callback will compare the XHR object of the response with the saved object.

最后,当您收到响应(成功回调)时,回调将把响应的XHR对象与保存的对象进行比较。

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

    // process the response
}

No jQuery errors.

没有jQuery错误。


As a general advice don't rely upon abort(), even for regular ajax requests.

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

  1. In any case you won't save resource on the server bacause the request you sent will be processed and there is no way to stop it. And a response will come back.

    无论如何,您不会在服务器上保存资源,因为您发送的请求将被处理,并且无法停止它。回应将会回来。

  2. Some (older) browsers handle abort() not properly.

    有些(旧的)浏览器处理abort()不正确。

Just "cache" the XHR object and handle the CANCEL scenario yourself.

只需“缓存”XHR对象并自己处理取消场景。

#5


0  

Trevor Burnham's answer is pretty good, but instead of tracking a request count, you should just compare the request to the XHR parameter, like so;

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

Calling doRequest again or _freeRequest once before the previous request has completed, will result in the "abortion" of said request by causing the if (this._request !== xhr) line to become true, since this._request will either be deleted or another request altogether.

在之前的请求完成之前,再次调用doRequest或_freeRequest一次,将导致if (this)导致上述请求的“流产”。_request != xhr)行变为true,因为这。_request要么被删除,要么被全部删除。

#1


-2  

In jQuery 1.5 all the Ajax APIs have a wrapper object around the native XHR objects. Take a look at:

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

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

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

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

#2


11  

The basic answer is simply the one given here: You can't really abort() a JSONP call. So the real question is, how do you avoid both superfluous callback invocations and the error you're seeing?

基本的答案就是这里给出的答案:您不能真正中止JSONP调用。所以真正的问题是,如何避免多余的回调调用和所看到的错误?

You can't use try...catch around the callback because it's asynchronous; you'd have to catch it from jQuery's end, and jQuery generally doesn't handle exceptions thrown from callbacks. (I discuss this in my book, Async JavaScript.) What you want to do instead is use a unique identifier for each Ajax call and, when the success callback is invoked, check whether that identifier is the same as it was when you made the call. Here's an easy implementation:

你不能用……捕获回调,因为它是异步的;您必须从jQuery端捕获它,而且jQuery通常不处理从回调抛出的异常。(我在《异步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...
  }
});

Here I'm taking advantage of the fact that anything you pass to $.ajax is attached to the object that's used as this in the callback.

这里我利用的是,任何东西都变成了$ajax附加到回调中使用的对象。

It'd be nice if jQuery made abort() do this for us, of course.

当然,如果jQuery让abort()为我们做这个就好了。

#3


1  

jsonpString overrides the callback function name in a jsonp request. This value will be used instead of 'callback' in the 'callback=?' part of the query string in the URL.

jsonpString重写jsonp请求中的回调函数名。这个值将在“callback=?”中使用,而不是“callback”。URL中查询字符串的一部分。

So {jsonp:'onJSONPLoad'} would result in 'onJSONPLoad=?' passed to the server. As of jQuery 1.5, setting the jsonp option to false prevents jQuery from adding the ?callback string to the URL or attempting to use =? for transformation. In this case, you should also explicitly set the jsonpCallback setting. For example, { jsonp: false, jsonpCallback: "callbackName" }

所以{jsonp:'onJSONPLoad'}会导致'onJSONPLoad=?传递到服务器。对于jQuery 1.5,将jsonp选项设置为false可以防止jQuery向URL添加?回调字符串或尝试使用=?为转换。在本例中,还应该显式地设置jsonpCallback设置。例如,{jsonp: false, jsonpCallback:“callbackName”}

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

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

jQuery adds ?callback=jQuery17109492628197185695_1339420031913 and later sets the request data as parameter to this callback, so you will have:

jQuery添加?callback=jQuery17109492628197185695_1339420031913,然后将请求数据作为这个回调的参数,

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

To avoid setting additional parameters to request a URL and calling callback, add this parameter to ajax method: jsonp:false, so it will be look like:

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

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

#4


1  

Do not abort the request

不要中止请求

Just store somewhere the XHR object

只需存储XHR对象的某个位置

theXHR = $.ajax(....

If the user cancel the request null the saved object

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

// user canceled
theXHR = null;

Finally when you receive the response (success callback) the callback will compare the XHR object of the response with the saved object.

最后,当您收到响应(成功回调)时,回调将把响应的XHR对象与保存的对象进行比较。

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

    // process the response
}

No jQuery errors.

没有jQuery错误。


As a general advice don't rely upon abort(), even for regular ajax requests.

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

  1. In any case you won't save resource on the server bacause the request you sent will be processed and there is no way to stop it. And a response will come back.

    无论如何,您不会在服务器上保存资源,因为您发送的请求将被处理,并且无法停止它。回应将会回来。

  2. Some (older) browsers handle abort() not properly.

    有些(旧的)浏览器处理abort()不正确。

Just "cache" the XHR object and handle the CANCEL scenario yourself.

只需“缓存”XHR对象并自己处理取消场景。

#5


0  

Trevor Burnham's answer is pretty good, but instead of tracking a request count, you should just compare the request to the XHR parameter, like so;

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

Calling doRequest again or _freeRequest once before the previous request has completed, will result in the "abortion" of said request by causing the if (this._request !== xhr) line to become true, since this._request will either be deleted or another request altogether.

在之前的请求完成之前,再次调用doRequest或_freeRequest一次,将导致if (this)导致上述请求的“流产”。_request != xhr)行变为true,因为这。_request要么被删除,要么被全部删除。