views:

660

answers:

3

I'm writing a JavaScript widget, which is intended for use on other website and loads additional script files from my own web site (which basically means no XHR due to cross-domain limitations). Now I want to handle failures gracefully - if one script fails to load, I want to load the script from an alternate server.

I managed to handle server failures where the 1st server returns an error, but I also want to handle a timeout - if the 1st server takes too long to respond I want to abort the load and switch to the alternate.

The problem I have is that I can setup a timeout to trigger a method that switches to the alternate server, but the script from the alternate server doesn't load successfully until the browser itself times-out on the original request - which is way too long for my needs.

I want to be able to - while the 1st <script> tag is loading - abort the load, and add a second <script> tag that points to the alternate server.

I've tried setting the original script's src attribute to null, and even removing the tag from the HEAD element using removeNode(), but to no effect.

This all was tried on Firefox - I haven't tried IE yet, but the solution has to work on both. I'd love to hear any suggestions.

A: 

I am thinking you might want to structure your widget to use XMLHttpRequest which can be aborted via window.setTimeout().

Scott Evernden
Possibly, but due to the cross-domain issues noted above this is not feasable
Guss
oh missed it -- right up there / you already ruled this out .. ok, never mind
Scott Evernden
+1  A: 

Unfortunately it's not possible to cancel the request for tags. Historically browsers only allow 2 requests at the same time to one hostname, so it should be possible to load the second script from another server.

Do you initiate the script loading before body.onload? For a normal page load the browser waits for each script to load before continuing since the scripts can alter the document. If the script is not modifying the document, you can use the defer attribute so the browser continues to render the document while your script loads.

jQuery has a few open requests on a similar feature: http://dev.jquery.com/ticket/1863 http://dev.jquery.com/ticket/3442

gregers
I'm trying to load the second script from the same server (same hostname anyway - its load balanced so its probably a different server). This all happens after DOMReady and in the HEAD element so it would not delay page rendering. BTW "defer" is only supported on IE.
Guss
Many browsers still have max 2 simultaneous requests to the same hostname. So that might be what prevent you from loading the second script - if you're loading an image or something else from the same hostname. Try creating a new subdomain that also use the load balancer.
gregers
that sounds like it might work. I'll check it out!
Guss
A: 

If you can modify the script that's being loaded you can add a callback there. Just set a timer at the top of the your page and clear it at the bottom of your script file. This way if your script doesn't load properly, the backup request will be executed when the timer runs out.

At the top of your page run the following in an inline script block:

doneLoading = function() {
  clearTimeout(timeout);
}

timeout = setTimeout(function() {
             ... change the .src on the old inline script element here ...
                     }, 15000);

At the bottom of your external JavaScript file just call doneLoading(). If your initial request takes longer than 15 seconds, a new request to a backup server will run. I don't think you can abort the initial request, but the backup request will execute as expected.

mustpax
I can handle if the script fails to load or loads broken, the problem is what to do if the script takes forever to load - I want to abort to the backup early, before the browser time out expires.
Guss
setTimeout() will be called from the parent page body. So the timer will expire and initiate the backup request even if (and when) the first try fails.
mustpax