Question

I'm writing an AJAX web app that uses Comet/Long Polling to keep the web page up to date, and I noticed in Chrome, it treats the page as if it's always loading (icon for the tab keeps spinning).

I thought this was normal for Google Chrome + Ajax because even Google Wave had this behaviour.

Well today I noticed that Google Wave no longer keeps the loading icon spinning, anyone know how they fixed this?

Here's my ajax call code

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);
Was it helpful?

Solution

I shamelessly stole Oleg's test case and adjusted it a bit to simulate long-polling.

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>

The result is interesting: in Firefox and Opera, no loading indicator is shown during XMLHTTPRequests. Chrome lets it spinning... I suspect Google Wave doesn't use long polling anymore (but, for instance, polls every X seconds, to save resources), but I can't test it, as I don't have an account.

EDIT: And I figured it out: after adding a little delay in loading test.php, which can be as small as possible, the loading indicator stops after load.html has been loaded:

jQuery(document).ready(function() {
  setTimeout(function () {
    $('#main').load("test.php");
  }, 0);
});

Somehow, as is confirmed in a comment on another answer, when the browser gets control back to finish page rendering, the indicator stops spinning. Another advantage is that the request cannot be aborted by pressing Esc.

OTHER TIPS

Sorry for my general answer, but if you want to have a program which are more browser independent you should use jQuery or other your favorite library instead of low level XMLHttpRequest and ActiveXObject("Microsoft.XMLHTTP").

EDITED: I create two very simple HTML files: test.htm and load.htm and placed there in the same directory on a web site (try this one URL http://www.ok-soft-gmbh.com/jQuery/load/load.htm). I can't see effect which you describes in you question. Compare this files with your examples and you will solve your problem.

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>

I'm not sure about jQuery or Ajax, but I had a similar problem with inserting snippets into Ace Editor with the Snippet Manager. When inserting code into the editor right when the page was loading the page would seem to never load - the tab icon would spin forever. .setTimeout() only worked very inconsistently. It would work when the page loaded very quickly, but not when the page loaded more slowly. That might be because I wasn't wrapping anything in $(document).ready() - I was only calling my code at the end of the document body.

Here's a no-jQuery solution I found to my forever-spinning tab icon problem:

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

        clearInterval(tillPageLoaded);
        // load whatever

    }    
}, 5);

In my case, // load whatever was:

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

use this function

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;
};
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top