使用 jQuery 中止 JSONP ajax 请求
Posted
技术标签:
【中文标题】使用 jQuery 中止 JSONP ajax 请求【英文标题】:Abort JSONP ajax request with jQuery 【发布时间】:2011-09-22 06:50:04 【问题描述】:我正在使用 JSONP ajax 调用从不同的域加载一些内容,如果用户在按钮上引起“鼠标悬停”,所有这些内容都会执行。
我可以将 $.ajax() 调用返回捕获为 xhr 对象,并在每次用户导致“鼠标悬停”时中止 ajax 请求。但是JSONP回调函数仍然被调用,这会导致错误,我认为这是因为xhr.abort()方法并没有阻止回调函数被调用。
我尝试使用 trycatch(e) 包围 $.ajax() 调用,但在调用 xhr.abort() 方法后,错误仍然存在。
有没有办法处理这个异常?
引发的异常是这样的(根据 Firebug): jQuery16102234208755205157_1308941669256 不是函数
而异常的内部结构是这样的: jQuery16102234208755205157_1308941669256(...我来自不同域的json数据...)
【问题讨论】:
Kill ajax requests using javascript using jquery.的可能重复 我想这不是那么重复,因为这个问题是关于在 JSONP ajax 请求上调用 jqxhr.abort() 方法之后防止异常,而不是关于如何停止请求本身。 这个问题的答案可以在重复问题***.com/questions/9533848/…找到 非常老的问题。今天偶然发现了同样的问题。我添加了我的贡献。我不知道我的答案是否值得被接受,但可以肯定的是,接受的答案不应该是当前(被否决的)答案 【参考方案1】:基本的答案就是给定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()
为我们做这件事就好了。
【讨论】:
【参考方案2】:不要中止请求
只需将$.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 请求。
在任何情况下,您都不会在服务器上节省资源,因为您发送的请求将被处理并且无法停止。并且会有回应。
一些(旧)浏览器无法正确处理abort()
。
只需“缓存”jqXHR 对象并自己处理CANCEL 场景。
【讨论】:
第三个参数 XHR 从不匹配 $.ajax 返回的对象 @JackCole 我试过了,实际上是的,确实如此。在控制台上试试这个:jqxhr1=$.ajax(url: "/", success: function(data,status,jqxhr2)alert(jqxhr1===jqxhr2);)
我得到的是true
【参考方案3】:
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,
...
);
【讨论】:
【参考方案4】: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
将被删除或完全是另一个请求。
【讨论】:
【参考方案5】:在 jQuery 1.5 中,所有 Ajax API 都有一个围绕原生 XHR 对象的包装器对象。看看:
http://api.jquery.com/jQuery.ajax/#jqXHR
jqxhr.abort(); // should be what you're looking for
【讨论】:
这是我现在使用的。这将中止 ajax 请求。但是这个 ajax 请求使用 JSONP。在我使用“abort()”方法之后,调用了一个由 jQuery 内部生成的用于处理 JSONP 响应的 javascript 函数,但是 abort 方法似乎删除了该函数定义,或者什么,因为有一个我没有的异常能够应付。 您还有更多信息吗?现场示例,异常消息?以上是关于使用 jQuery 中止 JSONP ajax 请求的主要内容,如果未能解决你的问题,请参考以下文章