I provide a JavaScript widget to several web sites, which they load asynchronously. My widget in turn needs to load a script provided by another party, outside my control.
There are several ways to check whether that script has successfully loaded. However, I also need to run different code if that script load has failed.
The obvious tools that don't work include:
I'm not willing to use JavaScript libraries, such as jQuery. I need a very small script to minimize my impact on the sites that use my widget.
I want to detect the failure as soon as possible, so using a timer to poll it is undesirable. I wouldn't mind using a timer as a last resort on old browsers, though.
I've found the
<script>
tag'sonerror
event to be unreliable in some major browsers. (It seemed to depend on which add-ons were installed.)Anything involving
document.write
is right out. (Besides that method being intrinsically evil, my code is loaded asynchronously sodocument.write
may do bad things to the page.)
I had a previous solution that involved loading the <script>
in a new <iframe>
. In that iframe, I set a <body onload=...>
event handler that checked whether the <script onload=...>
event had already fired. Because the <script>
was part of the initial document, not injected asynchronously later, onload
only fired after the network layer was done with the <script>
tag.
However, now I need the script to load in the parent document; it can't be in an iframe any more. So I need a different way to trigger code as soon as the network layer has given up trying to fetch the script.
I read "Deep dive into the murky waters of script loading" in an attempt to work out what ordering guarantees I can count on across browsers.
If I understand the techniques documented there:
- I need to place my failure-handling code in a separate
.js
file. - Then, on certain browsers I can ensure that my code runs only after the third-party script either has run or has failed. This requires browsers that support either:
- Setting the
<script async>
attribute to false via the DOM, - or using
<script onreadystatechange=...>
on IE 6+.
- Setting the
Despite looking at the async support table, I can't tell whether I can rely on script ordering in enough browsers for this to be feasible.
So how can I reliably handle failure during loading of a script I don't control?
Have you considered using the window's onerror handler? That will let you detect when most errors occur and you can take appropriate action then. As a fallback for any issues not caught this way you can also protect your own code with try/catch.
You should also check that the third-party script actually loaded:
Then check if it loaded:
You can check which script caused the error using the
url
parameter.I believe I've solved the question I asked, though it turns out this doesn't solve the problem I actually had. Oh well. Here's my solution:
We want to run some code after the browser finishes attempting to load a third-party script, so we can check whether it loaded successfully. We accomplish that by constraining the load of a fallback script to happen only after the third-party script has either run or failed. The fallback script can then check whether the third-party script created the globals it was supposed to.
Cross-browser in-order script loading inspired by http://www.html5rocks.com/en/tutorials/speed/script-loading/.