Chrome's loading indicator keeps spinning during XMLHttpRequest
Asked Answered
L

4

31

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);
Lucialucian answered 24/4, 2010 at 9:7 Comment(0)
Y
36

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.

Yearn answered 26/4, 2010 at 13:0 Comment(4)
But wouldn't polling every x seconds increase the load on the server? I guess it can go other way now that I think about it (Long Polling vs Poling every x seconds). But I'm not sure I'm convinced they switched from Long Polling.Lucialucian
@teehoo: I once read that long polling is heavy on resources, as many connections have to be kept open at the same time, something HTTP is not designed for. But I'm no expert in servers, so please correct me if I'm wrong.Yearn
I guess keeping connections open takes more memory, but opening and closing connections constantly takes more CPU + bandwidth? Thanks for looking into this, I'll verify it works when I get home.Lucialucian
Thanks works perfectly, It looks like this lets Chrome finish loading everything first, which allows the spinner to stop, and then its not allowed to start up again on an AJAX call.Lucialucian
B
2

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>
Birch answered 24/4, 2010 at 9:17 Comment(11)
I don't know who downvoted you, I'll put this back up to zero because I found it somewhat helpful. Ill try JQuery and report back.Lucialucian
try usage one line of code instead of you code fragment: $('#elementtoupdate').load(myURL); You can add also some fadeIn effects or other one.Birch
So I implemented JQuery, and it made my code a little cleaner, but I still get the constantly loading status.Lucialucian
The difference between my script and yours is that as soon the ajax loading finishes, I automatically restart a Comet Poll. Comet Polling is when the browser can wait up to a minute before the server responds. During this time the loader is still spinning. But only in Chrome, Firefox (correctly) looks as if its doing nothing.Lucialucian
If you have the same effect with both your old code and with the code used jQuery, then the problem exist in another place: HOW you use Comet Polling. And the solution of your problem one should search here. And the code fragment which you posted probably has no errors at all. Are you agree?Birch
"if you want to have a program which are more browser independent you should use jQuery": not necessary, as those libraries essentially do the same. The method shown by the OP is as browser independent as the jQuery method.Yearn
BTW, you can't see the described problem because your (nice) test case doesn't use long-polling at all, the test.htm file is instantly served to the client. I think you should create a server side script that waits for 15 seconds or something to keep the connection open. And erm..., why do you assign an id to <head>?Yearn
In the sentence "if you want to have a program which are more browser independent you should use jQuery or other your favorite library..." I mean, that these libraries test in which browser the script are running and use corresponding browser depended code fragment. Those parts of code are very good tested in different environments from different people in the world. So if you want use this experience you should use "jQuery or other your favorite library".Birch
"id" to "head" element is of cause not really needed, but it not disturbs. This is not a perfect code, only a code example. I copied some part of code from my site.master page and forgot delete this "id".Birch
@Oleg: you (or such a library) shouldn't test in which browser you are (browser sniffing), there are lots of them. You should use feature detection (like in the XMLHTTPRequest example in the original question) to determine which function is available and use that one. See nczonline.net/blog/2009/12/29/…Yearn
The link, which you post, contains a good stuff, but a lot of features cannot be so easy detected. I like CSS usage, and I don't know another way as browser hacks and browser detection to be sure, that all will be good looking. I think that in the most situations I need do standard actions inside browser. One should not invent a wheel or a bicycle. I prefer to choose a good JavaScript library which are permanently been developing and been improving and use it. With the way I receive more quickly more stable, reliable and browser independent code. This is MY PERSONAL opinion.Birch
M
0

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' );
});
Melisamelisande answered 18/7, 2016 at 23:29 Comment(0)
G
-3

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;
};
Gesture answered 24/4, 2010 at 9:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.