views:

952

answers:

3

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);
+1  A: 

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"&gt;
<html xmlns="http://www.w3.org/1999/xhtml"&gt;
<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"&gt;&lt;/script&gt;
  <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>
Oleg
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.
teehoo
try usage one line of code instead of you code fragment: $('#elementtoupdate').load(myURL); You can add also some fadeIn effects or other one.
Oleg
So I implemented JQuery, and it made my code a little cleaner, but I still get the constantly loading status.
teehoo
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.
teehoo
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?
Oleg
"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.
Marcel Korpel
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>`?
Marcel Korpel
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".
Oleg
"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".
Oleg
@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 http://www.nczonline.net/blog/2009/12/29/feature-detection-is-not-browser-detection/
Marcel Korpel
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.
Oleg
A: 

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;
};
cosy
Can you format better ?
Romain Hippeau
+9  A: 

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"&gt;&lt;/script&gt;
  <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, even a tiny one, the loading indicator stops after load.html has been loaded:

jQuery(document).ready(function() {
  setTimeout(function () {
    $('#main').load("test.php");
  }, 500);
});
Marcel Korpel
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.
teehoo
@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.
Marcel Korpel
@Marcel 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.
teehoo
@teehoo: I just stumbled upon a comment in an answer that says the same: http://stackoverflow.com/questions/1064782/stop-the-browser-throbber-of-doom-while-loading-comet-server-push-iframe/1066729#1066729 (first comment)
Marcel Korpel
@Marcel, 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.
teehoo