views:

2066

answers:

6

I'm dynamically adding <script> tags to a page's <head>, and I'd like to be able to tell whether the loading failed in some way -- a 404, a script error in the loaded script, whatever.

In Firefox, this works:

var script_tag = document.createElement('script');
script_tag.setAttribute('type', 'text/javascript');
script_tag.setAttribute('src', 'http://fail.org/nonexistant.js');
script_tag.onerror = function() { alert("Loading failed!"); }
document.getElementsByTagName('head')[0].appendChild(script_tag);

However, this doesn't work in IE or Safari.

Does anyone know of a way to make this work in browsers other than Firefox?

(I don't think a solution that requires placing special code within the .js files is a good one. It's inelegant and inflexible.)

A: 

I don't know how to get this to work, but if you want to load JavaScript in dynamically, I know that loading a JavaScript with jQuery will run the script, or just loading JavaScript with any AJAX functions and eval() it should work.

Xunil
+2  A: 

There is no error event for the script tag. You can tell when it is successful, and assume that it has not loaded after a timeout:

<script type="text/javascript" onload="loaded=1" src="....js"></script>
Diodeus
The "onload" listener will be fired even if there's a javascript error.
Luca Matteis
Well, yes if the file LOADS and there is an error in the file itself, but if the file is not served up, the onload will never fire.
Diodeus
yes, true, that's why I asked to be more specific of what kind of error he's looking for.
Luca Matteis
Ok, sorry for the downvote, seems like he's looking for both 404 error (which will work with your solution), and also javascript error, which will work with mine.
Luca Matteis
+1  A: 

To check if the javascript in nonexistant.js returned no error you have to add a variable inside http://fail.org/nonexistant.js like var isExecuted = true; and then check if it exists when the script tag is loaded.

However if you only want to check that the nonexistant.js returned without a 404 (meaning it exists), you can try with a isLoaded variable ...

var isExecuted = false;
var isLoaded = false;
script_tag.onload = script_tag.onreadystatechange = function() {
    if(!this.readyState ||
        this.readyState == "loaded" || this.readyState == "complete") {
        // script successfully loaded
        isLoaded = true;

        if(isExecuted) // no error
    }
}

This will cover both cases.

Luca Matteis
It works, but doesn't really do what I want -- a failure in that case would never fire an event. I don't want to have to poll for a variable and, if it's still false after a few seconds, fire the on-fail callback.
David
What kind of error are you trying to retrieve? Failure to load? Failure to execute the javascript in nonexstant.js? HTTP Response Error? Please be more descriptive.
Luca Matteis
Any of the above would be good. I specifically care about a 404 error, though.
David
404, meaning you want to check if the file nonexistant.js doesn't exist? But if it does you want to check if it returned no error?
Luca Matteis
+1  A: 

The reason it doesn't work in Safari is because you're using attribute syntax. This will work fine though:

script_tag.addEventListener('error', function(){/*...*/}, true);

...except in IE.

If you want to check the script executed successfully, just set a variable using that script and check for it being set in the outer code.

Ant P.
That actually doesn't make any difference for Safari -- it still doesn't fire the error handler.
David
I had a problem with an onclick handler in safari and this was what fixed it, so I thought it'd be the same for onerror too. Apparently not...
Ant P.
A: 

It was proposed to set a timeout and then assume load failure after a timeout.

setTimeout(fireCustomOnerror, 4000);

The problem with that approach is that the assumption is based on chance. After your timeout expires, the request is still pending. The request for the pending script may load, even after the programmer assumed that load won't happen.

If the request could be canceled, then the program could wait for a period, then cancel the request.

Garrett
A: 

Well, the only way I can think of doing everything you want is pretty ugly. First perform an AJAX call to retrieve the Javascript file contents. When this completes you can check the status code to decide if this was successful or not. Then take the responseText from the xhr object and wrap it in a try/catch, dynamically create a script tag, and for IE you can set the text property of the script tag to the JS text, in all other browsers you should be able to append a text node with the contents to script tag. If there's any code that expects a script tag to actually contain the src location of the file, this won't work, but it should be fine for most situations. Ugly, but will work. You can take a look at my quick and dirty example here: http://pastie.org/829775

nickjsify