【问题标题】:Timeouts on periodic ajax requests with jQuery使用 jQuery 的周期性 ajax 请求超时
【发布时间】:2010-07-30 10:27:05
【问题描述】:

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

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

文本状态:成功, XHR.readyState: 4, XHR.状态:0 所以我需要使用 XHR.status-value(成功时应该为 200)来确定错误。 这是正常行为还是我做错了什么?

【问题讨论】:

    标签: javascript jquery


    【解决方案1】:

    考虑在成功和错误处理程序中移动 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 线程有一个开口并在代码执行之间跳转。

    使用您之前的代码设置,由于 http 往返花费了不确定的时间,您还有机会在 refreshId 调用 2 之后到达 refreshId 调用 1 的响应。

    通过使您的 setTimeout 取决于传入的响应,您可以获得更稳定和透明的结果。

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 感谢您的回复。这工作正常。但是现在我用$.each(...) 而不是setInterval 也有同样的问题。我用它来加载多个图像。你有解决方法吗?
      • .ajax() 与周期性请求并行使用时,有时会出现同样的问题。有没有办法避免在成功函数中检查XHR.status==0
      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        我相信您应该研究一下 http://plugins.jquery.com/project/ajaxqueue,它旨在管理 ajax 竞争条件。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-04-07
          • 2015-10-24
          • 2014-03-13
          • 1970-01-01
          • 1970-01-01
          • 2012-04-22
          相关资源
          最近更新 更多