Chrome的加载指示器在XMLHttpRequest期间一直旋转

31

我正在编写一个使用 Comet/长轮询 来使网页保持更新的 AJAX 网络应用程序,在 Chrome 中,我发现它会将页面视为始终在加载中(标签的图标一直旋转)。

我原本以为这对于 Google Chrome + Ajax 是正常行为,因为即使 Google Wave 也有这种行为。

今天我发现 Google Wave 不再让加载图标旋转了,有人知道他们是如何解决这个问题的吗?

这是我的 Ajax 调用代码:

var xmlHttpReq = false;
// Mozilla/Safari
if (window.XMLHttpRequest) {
   xmlHttpReq = new XMLHttpRequest();
}
// IE
else if (window.ActiveXObject) {
   xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlHttpReq.open('GET', myURL, true);
xmlHttpReq.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xmlHttpReq.onreadystatechange = function() {
   if (xmlHttpReq.readyState == 4) {
      updatePage(xmlHttpReq.responseText);
   }
}
xmlHttpReq.send(null);
4个回答

36

我无耻地偷走了Oleg的测试用例,并稍微调整了一下以模拟长轮询。

load.html:

<!DOCTYPE html>
<head>
  <title>Demonstration of the jQery.load problem</title>
  <script src="http://code.jquery.com/jquery-latest.js"></script>
  <script>
  jQuery(document).ready(function() {
    $('#main').load("test.php");
  });
  </script>
</head>
<body>
  <div id='main'></div>
</body>
</html>

test.php:

<?php
  sleep(5);
?>
<b>OK!</b>
结果很有趣:在Firefox和Opera中,XMLHTTPRequests期间不会显示加载指示器。Chrome则让它旋转……我怀疑Google Wave不再使用长轮询(但例如每X秒轮询一次以节省资源),但我无法测试,因为我没有帐户。
编辑:我找到了解决方法:在加载test.php时添加一个小延迟(尽可能小),加载完成load.html后,加载指示器就会停止。
jQuery(document).ready(function() {
  setTimeout(function () {
    $('#main').load("test.php");
  }, 0);
});

在另一个答案的评论中确认,当浏览器重新掌控页面渲染时,指示器会停止旋转。另一个优点是请求不会因按下Esc而被中止。


但是每隔x秒进行轮询不会增加服务器的负载吗?我想现在考虑起来可能会有另一种方式(长轮询 vs 每隔x秒轮询)。但我不确定他们是否已经从长轮询转换过来了。 - Martin Konecny
@teehoo:我曾经读过,长轮询对资源消耗很大,因为必须同时保持许多连接,这是 HTTP 不设计的。但我不是服务器方面的专家,请纠正我如果我错了。 - Marcel Korpel
我猜保持连接会占用更多的内存,但是频繁地打开和关闭连接会占用更多的CPU和带宽?感谢您对此进行了调查,我回家后会验证它是否有效。 - Martin Konecny
谢谢,它完美地运行了。看起来这样可以让Chrome先完成所有加载,从而允许旋转器停止,然后在AJAX调用时不允许再次启动。 - Martin Konecny

2
抱歉我的回答不太具体,但如果您想要一个更加独立于浏览器的程序,建议使用jQuery或其他您喜欢的库,而不是低级的XMLHttpRequest和ActiveXObject("Microsoft.XMLHTTP")。
编辑后: 我创建了两个非常简单的HTML文件:test.htm和load.htm,并将它们放在同一个目录下的网站上(请尝试此URL:http://www.ok-soft-gmbh.com/jQuery/load/load.htm)。我无法看到您在问题中描述的效果。将这些文件与您的示例进行比较,您将解决问题。 load.htm:
<!DOCTYPE html PUBLIC
          "-//W3C//DTD XHTML 1.0 Strict//EN"
          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head">
  <title>Demonstration of the jQery.load problem</title>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <script src="http://code.jquery.com/jquery-latest.js"></script>
  <script type="text/javascript">
  jQuery(document).ready(function() {
    $('#main').load("test.htm");
  });
  </script>
</head>

<body>
  <div id='main'></div>
</body>
</html>

test.htm:

<b>OK!</b>

我不知道是谁给你点了踩,但我会把它恢复到零,因为我觉得这有些有用。我会尝试使用JQuery并回报结果。 - Martin Konecny
尝试使用一行代码而不是代码片段:$('#elementtoupdate').load(myURL); 您还可以添加一些fadeIn效果或其他效果。 - Oleg
如果你想要一个更加浏览器无关的程序,你应该使用jQuery。但其实这些库本质上是相同的。OP所展示的方法和jQuery方法一样具有浏览器无关性。 - Marcel Korpel
@Oleg:你(或者类似的库)不应该测试你所在的浏览器(浏览器嗅探),因为有很多种浏览器。你应该使用特性检测(就像原问题中的XMLHTTPRequest示例)来确定哪个函数可用并使用它。请参见http://www.nczonline.net/blog/2009/12/29/feature-detection-is-not-browser-detection/。 - Marcel Korpel
你发布的链接包含很好的内容,但很多功能不容易被检测到。我喜欢使用CSS,除了浏览器hack和浏览器检测,我不知道其他方法可以确保所有东西看起来都很好。我认为在大多数情况下,我需要在浏览器内执行标准操作。人们不应该重新发明轮子或自行车。我更喜欢选择一个不断发展和改进的好的JavaScript库并使用它。通过这种方式,我可以更快地获得更稳定、可靠和独立于浏览器的代码。这是我的个人意见。 - Oleg
显示剩余6条评论

0

我不确定jQuery或Ajax,但我曾经在使用Snippet Manager将代码片段插入Ace Editor时遇到类似的问题。当在页面加载时立即将代码插入编辑器时,页面似乎永远无法加载-选项卡图标会一直旋转。.setTimeout()只有在页面加载非常快时才能很不稳定地工作。这可能是因为我没有将任何内容包装在$(document).ready()中 - 我只在文档主体末尾调用了我的代码。

这是一个没有使用jQuery的解决方案,可以解决我的永远旋转的选项卡图标问题:

var tillPageLoaded = setInterval(function() {
    if( document.readyState === 'complete' ) {

        clearInterval(tillPageLoaded);
        // load whatever

    }    
}, 5);

在我的情况下,// 加载任何内容 是这样的:

ace.config.loadModule('ace/ext/language_tools', function () {
    myEditorInstance.insertSnippet( 'some string' );
});

-3
使用这个函数。
function getHTTPObject() {
 var xhr = false;
 if (window.XMLHttpRequest) {
  xhr = new XMLHttpRequest();
 } else if (window.ActiveXObject) {
  try {
   xhr = new ActiveXObject("Msxml2.XMLHTTP");
  } catch(e) {
   try {
    xhr = new ActiveXObject("Microsoft.XMLHTTP");
   } catch(e) {
    xhr = false;
   };
  };
 };
 return xhr;
};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接