2010-07-30 43 views
4

我用下面的代码来发送一个Ajax请求每3秒定期Ajax请求:超时与jQuery的

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); 

的问题是,即使家庭无法访问服务器(例如,不连接到局域网),将会调用成功函数,而不是使用“超时”状态(在Ubuntu 10.04上使用FireFox 3.6.7进行测试)的错误函数。
(无定期请求它会正常工作:在超时误差函数被调用正确的“timeout'-状态文本。)

成功的警报功能上会显示超时以下文字:

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

回答

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秒,你可以fireing新的人之前放弃你最后的(可能会运行)Ajax请求。

因此,一个变量分配给的.ajax()返回像

var currentxhr = $.ajax({}); 

,并添加一个beforeSend回调到您的通话.ajax()。在该处理程序调用

currentxhr.abort(); 

这将中止可能会运行的要求。

+0

感谢您的回复。这工作正常。但是现在我遇到了'$ .each(...)'而不是'setInterval'的问题。我用它来加载多个图像。你有解决方法吗? – Biggie 2010-07-30 12:26:43

+0

与定期请求并行使用'.ajax()'时,有时会出现同样的问题。有没有办法避免在成功函数中检查'XHR.status == 0'? – Biggie 2010-07-30 20:36:43

0

而不是看着textStatus使用这个测试:xhr.statusText.toUpperCase() === 'OK'

我遇到了一个问题,有上301页一xhr.status === 0 FF 3.6.8。我加了上面我的jQuery 1.4.2在httpSuccess功能:

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

思考上的成功和错误处理程序移动的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调用1的响应将refreshId呼叫2到达后由于HTTP往返服用时间未定ammount的。

通过让你的setTimeout依赖于响应,你会得到一个更稳定和透明的结果。