Cómo evitar la pérdida de llamadas a un archivo JS externo antes de cargarlo

My issue is that multiple websites are going to include my JS file and when calling something like this:

<script src="..."></script>

hello.say("yay");

there going to be a race issue so sometimes it could make it sometimes not. i know that i can solve that easily by putting every function in a window.onload but that wouldn't be clean as i've seen other websites magically solve that like google analytics:

.. Calling google analytics JS..

<script type="text/javascript">
try{
var pageTracker = _gat._getTracker("UA-xxxxxx-x");     <-- this an object !
pageTracker._trackPageview();
} catch(err) {}
</script>

¿Cómo hacer eso?

preguntado el 08 de enero de 11 a las 19:01

4 Respuestas

Google Analytics uses a trick that's a perfect example of something that can only be done in duck typed languages. The main object is an array if the GA-script hasn't loaded, but if it has it changes behaviour. Let's see if I can explain it.

I pulled this piece from the source here at stackoverflow:

var _gaq = _gaq || [];
_gaq.push(['_setAccount','UA-5620270-1']);
_gaq.push(['_trackPageview']);

It looks like an array with some values being pushed to it. In fact, if _gaq is falsedad when this code is run (as it is if no other analytics-JavaScript has run yet), it as an array. Then, when the main analytics script (included with a script-tag anywhere on the page) loads it examines this array and performs some task based on the contents of the array.

So, if this happens in opposite order (the main script is loaded first, and then the snippet above) the main script set _gaq to an object with a push-method that does whatever google wants it to do. Later, when the code above runs, _gaq.push doesn't just add values to an array; it actually executes arbitrary code (and doesn't push to an array at all).

Hence, regardless of which script runs first, the end result will be the same when both have finished.

Respondido el 08 de enero de 11 a las 22:01

If you include your file in the header part of the html page, it will be loaded before any other javascript in the page is run.

UPD: Also, I think even files included in the text of thml are downloaded before the processing of the rest of javascripts. Are you sure that is your problem in the first place?

Respondido el 08 de enero de 11 a las 22:01

gAnalytics snippet can be put anywhere. - CodeOverload

Yep, came up with that also afterwards. - Cray

You will need to delay the execution of any javascript code that depends on the external javascript until after the page has been fully loaded and you can do that by attaching the execution to the window.onload event.

window.onload = function() {
  hello.say('yay');
}

But this has the disadvantage of only working for one function and will override any functions that have been initially attached to that event. You would want to read Simon Wilson's post and the comments for solutions on how to handle this situation.

http://simonwillison.net/2004/May/26/addLoadEvent/

Respondido el 08 de enero de 11 a las 22:01

The first paragraph of this answer is rather faulty. You do not have to wait for window.onload to run code dependent on external JS; all JS is loaded and executed sequentially as it is encountered (unless explicitly directed otherwise), so really you can rely on code in an external JS file being loaded/executed even in a script tag immediately following it. What you cannot rely on there is the entire DOM of the page being ready, which is usually what people wait for window.onload for (but there are better ways of doing this as well, e.g. the DOMContentLoaded event in all browsers but IE). - Ken Franqueiro

Thanks for the clarification Ken, so in effect, if there are several javascript tags in a page, they are loaded sequentially and not in parallel as other external content like images and css on a page? - takinbo

I'm a bit unsure as to what you think the race issue is here.

Browsers always* execute script tags in the order they see them. If this were not true, a good portion of the internet would break - as well as pretty much every common JavaScript library in existence.

So, as long as users load your script earlier in the document than when they call its APIs, you should have no problem. The only potential exception to this I can think of is if your script's initialization relies on asynchronous logic, in which case you should think about providing a standard callback mechanism of your own for users to write their code in.

If users might load your script AFTER the point they use its APIs, then the trick Jakob alludes to in his answer would work. But I'm not even sure you're aiming for that level of complexity.

*edit: I should note, to be perfectly honest, there are specific exceptions to this, but not so long as you're simply dealing with standard non-deferred usage of <script> tags within an HTML document.

Respondido el 09 de enero de 11 a las 00:01

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.