使用jQuery定期ajax请求超时

时间:2010-07-30 10:27:06

标签: javascript jquery

我使用以下代码每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的错误函数(在Ubuntu 10.04上测试)使用FireFox 3.6.7) (如果没有定期请求,它将正常工作:在超时时,使用正确的'timeout'-statusText调用错误函数。)

success-alert-function将在超时时显示以下文字:

    textStatus: success,
    XHR.readyState: 4,
    XHR.status: 0
所以我需要使用XHR.status值,成功时应该是200,以确定错误。 这是正常行为还是我做错了什么?

4 个答案:

答案 0 :(得分:3)

考虑在成功和错误处理程序中移动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依赖于所引入的响应,你可以获得更稳定和透明的结果。

答案 1 :(得分:0)

好吧,搞乱异步函数回调可能会变得凌乱:)。 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()的返回

var currentxhr = $.ajax({});

并在beforeSend来电中添加.ajax()个回调。在该处理程序调用中

currentxhr.abort();

这将中止可能正在运行的请求。

答案 2 :(得分:0)

而不是查看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');            

答案 3 :(得分:0)

我相信你应该研究http://plugins.jquery.com/project/ajaxqueue,这是为了管理ajax竞争条件。