使用jQuery定期ajax请求超时
我使用以下代码每3秒发送一次ajax请求:
var refreshId = setInterval(function() { $.ajax({ async: true, url: 'gohere', dataType: 'text', cache: false, timeout: 5000, success: function(result, textStatus, XMLHttpRequest) { alert('textStatus: ' + textStatus + ",\nXHR.readyState: " + XMLHttpRequest.readyState + ",\nXHT.status: " + XMLHttpRequest.status); }, error: function(XMLHttpRequest, textStatus, errorThrown) { alert('textStatus: ' + textStatus + ",\nXHR.readyState: " + XMLHttpRequest.readyState + ",\nXHT.status: " + XMLHttpRequest.status); } }); }, 3000);
问题是,即使家庭服务器不可访问(例如未连接到LAN),也会调用成功函数而不是带有“timeout”-status的错误函数(在带有FireFox 3.6的Ubuntu 10.04上测试) 0.7)。
(没有定期请求它将正常工作:在超时时,使用正确的’timeout’-statusText调用错误函数。)
success-alert-function将在超时时显示以下文本:
textStatus:成功, XHR.readyState:4, XHR.status:0
所以我需要使用XHR.status值,成功时应该是200,以确定错误。 这是正常行为还是我做错了什么?
思考在成功和error handling程序中移动setTimeout而不是异步递归。
var refreshId = function() { $.ajax({ async: true, url: 'gohere', dataType: 'text', cache: false, timeout: 5000, success: function(result, textStatus, XMLHttpRequest) { alert('textStatus: ' + textStatus + ",\nXHR.readyState: " + XMLHttpRequest.readyState + ",\nXHT.status: " + XMLHttpRequest.status); setTimeout(refreshId, 3000); }, error: function(XMLHttpRequest, textStatus, errorThrown) { alert('textStatus: ' + textStatus + ",\nXHR.readyState: " + XMLHttpRequest.readyState + ",\nXHT.status: " + XMLHttpRequest.status); setTimeout(refreshId, 3000); } }); };
事实是,setTimeout和setInterval时间不可靠,尤其是警报。 只要警报对话框保持打开状态,警报就会停止javascript。 此外,setTimeout和setInterval不会中断当前运行的代码以保证完美的时序,它们将等到javascript线程在代码执行之间有一个开放和跳转。
使用之前的代码设置,您还有可能在refreshId调用2之后,refreshId调用1的响应将到达,因为http往返占用了未确定的时间。
通过使您的setTimeout依赖于响应,您将获得更稳定和透明的结果。
好吧,搞乱异步函数回调可能会变得凌乱:)。 setInterval()
就是其中之一,也就是.ajax()
。
您应该尝试使用setTimeout()
并在最后一次完成时触发下一个.ajax()
调用。
(function repeat(){ $.ajax({ async: true, url: 'gohere', dataType: 'text', cache: false, timeout: 5000, success: function(result, textStatus, XMLHttpRequest) { alert('textStatus: ' + textStatus + ",\nXHR.readyState: " + XMLHttpRequest.readyState + ",\nXHT.status: " + XMLHttpRequest.status); }, error: function(XMLHttpRequest, textStatus, errorThrown) { alert('textStatus: ' + textStatus + ",\nXHR.readyState: " + XMLHttpRequest.readyState + ",\nXHT.status: " + XMLHttpRequest.status); }, complete: function(XMLHttpRequest){ setTimeout(repeat, 3000); } }); }());
如果你坚持要让.ajax()
尽可能接近3
秒,你可以在激活新的ajax请求之前中止你的最后一个(可能正在运行的)ajax请求。
因此,将变量赋给.ajax()
的返回值
var currentxhr = $.ajax({});
并在您的.ajax()
调用中添加beforeSend
回调。 在该处理程序调用中
currentxhr.abort();
这将中止可能正在运行的请求。
而不是查看textStatus
使用此测试: xhr.statusText.toUpperCase() === 'OK'
我遇到了FF 3.6.8在301页面上有xhr.status === 0
问题。 我在httpSuccess
函数中将上面的内容添加到我的jQuery 1.4.2中:
return !xhr.status && location.protocol === "file:" || // Opera returns 0 when status is 304 ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status === 304 || xhr.status === 1223 || ( xhr.status === 0 && xhr.statusText.toUpperCase() === 'OK');
我相信你应该研究http://plugins.jquery.com/project/ajaxqueue ,这是为了管理ajax竞争条件。