使用jQuery中止JSONP ajax请求
我使用JSONPAJAX调用从不同的域加载一些内容,如果用户在按钮上引起“鼠标悬停”,那么所有这些内容都会执行 我可以将$.ajax()调用返回捕获为xhr对象,并使用它在每次用户导致“鼠标悬停”时中止ajax请求。但是仍然会调用JSONP回调函数,这会导致一个错误,我认为这是因为xhr.abort()方法没有阻止调用回调函数 我尝试过用try{}catch(e){}围绕$.ajax()调用,但是在调用xhr.abort()方法之后,错误仍然存在 有没有办法处理这个异常 引发的异常如下(根据Firebug): jquery16102324208755205157_1308941669256不是一个函数 异常的内部结构如下所示:使用jQuery中止JSONP ajax请求,jquery,ajax,callback,jsonp,abort,Jquery,Ajax,Callback,Jsonp,Abort,我使用JSONPAJAX调用从不同的域加载一些内容,如果用户在按钮上引起“鼠标悬停”,那么所有这些内容都会执行 我可以将$.ajax()调用返回捕获为xhr对象,并使用它在每次用户导致“鼠标悬停”时中止ajax请求。但是仍然会调用JSONP回调函数,这会导致一个错误,我认为这是因为xhr.abort()方法没有阻止调用回调函数 我尝试过用try{}catch(e){}围绕$.ajax()调用,但是在调用xhr.abort()方法之后,错误仍然存在 有没有办法处理这个异常 引发的异常如下(根据Fi
jquery16102324208755205157_1308941669256({…来自不同域的json数据…})在jquery1.5中,所有Ajax API都在原生XHR对象周围有一个包装器对象。看看:
基本答案很简单:您不能真正地
abort()
JSONP调用。所以真正的问题是,如何避免多余的回调调用和看到的错误
您不能在回调周围使用try…catch
,因为它是异步的;您必须从jQuery端捕获它,而jQuery通常不会处理回调抛出的异常。(我在我的书中讨论过这一点,)您想要做的是为每个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()
为我们做这件事就好了。jsonpString在jsonp请求中重写回调函数名。在URL中查询字符串的“callback=?”部分,将使用此值代替“callback”
因此,{jsonp:'onJSONPLoad'}
将导致'onJSONPLoad=?'
传递给服务器。从jQuery1.5开始,将jsonp选项设置为false可以防止jQuery将?回调
字符串添加到URL或尝试使用=?
进行转换。在这种情况下,还应该显式设置jsonpCallback
设置。例如,{jsonp:false,jsonpCallback:“callbackName”}
jQuery添加了?callback=jQuery17109492628197185695_133942031913
,并在以后将请求数据设置为此回调的参数,因此您将有:
jQuery17109492628197185695_1339420031913({
"status": 200,
"data": {your json}
})
为了避免设置额外的参数来请求URL和调用回调,请将此参数添加到ajax方法:jsonp:false
,这样看起来像:
$.ajax({
...
jsonp:false,
...
});
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
或\u freeRequest
将导致if(this.\u request!==xhr)
行变为true,从而导致所述请求的“流产”,由于此请求将被删除或另一个请求一起删除。请勿中止请求
只需将$.ajax()
如果用户取消请求,则保存的对象为空
// user canceled
theJqXHR = null;
最后,当您收到响应(success
callback)时,回调会将响应的jqXHR对象与保存的对象进行比较
function successCallback(data, textStatus, jqXHR )
{
if( theJqXHR !== jqXHR )
{
// user canceled; discard the response
return;
}
// process the response
}
没有jQuery错误
一般建议不要依赖于abort()
,即使对于常规ajax请求也是如此
在任何情况下,您都不会在服务器上保存资源,因为您发送的请求将被处理,无法停止。然后会有回应
某些(较旧的)浏览器无法正确处理abort()
只需“缓存”jqXHR对象并自己处理取消场景。可能的重复我想这不是重复,因为这个问题是关于在JSONP ajax请求中调用jqXHR.abort()方法后防止异常,不是关于如何停止请求本身。这个问题的答案可以在重复问题非常旧的问题中找到。今天偶然发现了同样的问题。我添加了我的贡献。我不知道我的答案是否值得被接受,但可以肯定的是,被接受的答案不应该是当前的(被否决的)答案。这就是我现在正在使用的答案。这将中止ajax请求。但是这个ajax请求使用JSONP。在我使用“abort()”方法之后,会调用jQuery内部生成的javascript函数来处理JSONP响应,但abort方法似乎删除了该函数定义或其他内容,因为有一个我无法处理的异常。您有更多信息吗?例如,异常消息?第三个参数XHR从未与$返回的对象匹配。ajax@JackCole我试过了,事实上,是的,的确如此。在控制台上尝试以下操作:jqxhr1=$.ajax({url:“/”,success:function(数据、状态、jqxhr2){alert(jqxhr1==jqxhr2);}}})
我得到的是true
// user canceled
theJqXHR = null;
function successCallback(data, textStatus, jqXHR )
{
if( theJqXHR !== jqXHR )
{
// user canceled; discard the response
return;
}
// process the response
}