使用 jQuery 中止 JSONP ajax 请求

发布于 2024-11-17 05:10:46 字数 494 浏览 2 评论 0原文

我正在使用 JSONP ajax 调用来加载来自不同域的一些内容,并且如果用户在按钮上引起“鼠标悬停”,则所有这些内容都会被执行。

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

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

有没有办法处理这个异常?

引发的异常是这样的(根据Firebug): jQuery16102234208755205157_1308941669256 不是一个函数

而异常的内部结构是这样的: jQuery16102234208755205157_1308941669256({...我来自不同域的json数据...})

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.

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.

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

Is there a way to handle that exception?

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

爱给你人给你 2024-11-24 05:10:46

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

您不能在回调周围使用 try...catch 因为它是异步的;你必须从 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...
  }
});

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

当然,如果 jQuery 让 abort() 为我们做这件事,那就太好了。

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?

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:

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.

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

东北女汉子 2024-11-24 05:10:46

不要中止请求

只需将 $.ajax() 返回的 jqXHR 对象存储在某处

theJqXHR = $.ajax(....

如果用户取消请求 null 保存的对象

// 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()

只需“缓存”jqXHR 对象并自行处理CANCEL 场景。

Do not abort the request

Just store somewhere the jqXHR object returned by $.ajax()

theJqXHR = $.ajax(....

If the user cancel the request null the saved object

// user canceled
theJqXHR = null;

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

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

    // process the response
}

No jQuery errors.


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

  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.

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

烟花肆意 2024-11-24 05:10:46

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,
  ...
});

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.

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

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:

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:

$.ajax({
  ...
  jsonp:false,
  ...
});
寒冷纷飞旳雪 2024-11-24 05:10:46

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) 行变为 true,因为 this._request 将被删除或完全另一个请求。

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;

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.

攒一口袋星星 2024-11-24 05:10:46

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

http://api.jquery.com/jQuery.ajax/#jqXHR< /a>

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

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

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

 jqxhr.abort(); // should be what you're looking for
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文