Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stop the browser “throbber of doom” while loading comet/server push XMLHttpRequest

(This question is similar to this one, but it's for using XMLHttpRequest instead of an iframe for Comet.)

I'm starting an async long poll like this:

var xhr = new XMLHttpRequest();
xhr.open('POST', url);
xhr.send();

If I do this inside <script>...</script> in the head, it will cause the document to keep loading forever. (I'm testing this in Safari on Mac OS X and the iPhone, and it's the only browser I need to support).

Using DOMContentLoaded or load events won't work.

Using a setTimeout with a large enough delay will work. 0 won't, 1000 will, 100 will some times and not other times. I don't feel comfortable with this.

The only way I found that works is the combination of both:

document.addEventListener('DOMContentLoaded', function () {
    setTimeout(function () {
        var xhr = new XMLHttpRequest();
        xhr.open('POST', url);
        xhr.send();
    }, 0);
});

I guess this solves the problem for now, but I'm still afraid it will break in the future. // Edit: this doesn't work reliably either.

Does anyone know of a more reliable way?

like image 505
Jaka Jančar Avatar asked Nov 14 '09 20:11

Jaka Jančar


2 Answers

I'm not sure, but it seems that if the browser shows that it's still downloading then that's entirely correct - isn't that basically what Comet programming is? The server is still sending unbuffered content and when that streams in a block of javascript it's executed, allowing the server to push events to the client browser.

In the Ajax early days (for instance on IE6 where XMLHttpRequest was a separate ActiveX object) I'd of expected the browser to not know that it was still waiting.

But in Safari 4, Chrome, FX3.5 and all the modern browsers the XMLHttpRequest is built in - it knows that it's still waiting for the server to still stream its content, exactly as it would with and <IFrame>

In short - I'd expect any Comet approach to show that the browser was still downloading because it is. I'd expect any workaround you find to get fixed in future builds because Comet is essentially a hack to get a server-push model working.

However they have started to built real server-push support into HTML 5.

Does mobile Webkit support the HTML 5 draft event-source tag yet? If so you could potentially try that.

Then you would have something like this:

<!-- new HTML 5 tag supporting server-push -->
<event-source src="http://myPushService.com" id="service">

<script type="text/javascript">

    function handleServiceEvent(event) {
        // do stuff
    }

    // tell browser to fire handleServiceEvent in response to server-push
    document.getElementById('service').addEventListener('event name', handleServiceEvent, false);
</script>
like image 154
Keith Avatar answered Sep 29 '22 11:09

Keith


When you say:

...it will cause the document to keep loading forever.

What exactly do you mean by this? Do you mean that the progress bar never finishes? Or is the actual document not even fully visible? It's not likely that an AJAX request would stop the entire document from loading, but anyway ...

Case 1: The progress bar never finishes

This is likely caused by the AJAX request never completing. Have you tried looking at the AJAX request in a Firebug console? It will show you both the request made and the server's response. I would start here just to make sure the server is sending something back.

Case 2: The document elements are not fully loaded/visible

You can try putting your <script> tag right before the </body> tag.

When you do this, the DOM tree is fully loaded before the script even executes, you don't have to wait for 'domready' or 'onload' to fire. Also, keep in mind that the DOM tree being loaded does not mean DOM content (such as images) have fully loaded (you would need to wait for 'onload' to be sure of that)

In either case, I would try putting the script right before the </body> tag, so the DOM skeleton has a chance to be built.

Side note:

Are you viewing your page with any type of debugger? (Firebug, Webkit Inspector). Webkit Inspector in particular will actually stop the entire document from processing if you have the console open AND a JavaScript error is encountered. Do you see any JavaScript errors in the console? Does the page load if you turn off your debuggers?

like image 26
Matt Avatar answered Sep 29 '22 13:09

Matt