How my web site works is that it needs to load two external JavaScript files:

Google Maps v3 JavaScript, and

JQuery JavaScript

Then, I have inline JavaScript within the HTML that cannot be executed until those two files above are downloaded.

Once it loads these external javascript files, it then, and only then, can dynamically render the page. The reason why my page can't load until both Google Maps and JQuery are loaded is that - my page, based on the geolocation (using Gmaps) of the user will then display the page based on where they are located (e.g. New York, San Francisco, etc). Meaning, two people in different cities viewing my site will see different frontpages.

Question: How can I get my JavaScript files to download asynchronously so that my overall page load time is quickest?

UPDATE:

If I were to download, somehow, Google-maps and JQuery asynchronously, how would I create an event that would be fired once both Google-maps and JQuery have downloaded since my page has a hard dependency on those files to execute.

UPDATE 2

Even though there are 3 answers below, none still actually answer the problem I have. Any help would be greatly appreciated.

you should move all the inline javascript out to un-obtrustive javascript and that will fix some of your problems.
–
Jarrod RobersonMay 10 '10 at 15:17

In regard to your update, just create a function that is called when each of your scripts is loaded, and have it call your other code on the second time it's called. I.e. the first time it's called, set a variable, and the second time (when it notices the variable is set), run your code.
–
tloflinMay 10 '10 at 15:43

@tloflin, what you just described is creating a "waterfall effect", which is not asynch.
–
TeddykMay 10 '10 at 15:49

@Teddyk, if you want your code to wait until a condition is fulfilled (such as loading two scripts), that is by definition not "asynch". In what way do you want it to be asynchronous? You should be able to make it exactly as asynchronous as the scripts themselves.
–
tloflinMay 10 '10 at 17:12

@Tloflin, I want them to begin downloading at the same time. that's what I mean by asynch
–
TeddykMay 11 '10 at 2:28

That was also my first thought, but the both scripts actually originate from different domains. I'd after all just say: it's browser specific behaviour. In Firefox the downloads per domain is by the way configureable as network.http.max-connections in about:config. It defaults to 15.
–
BalusCMay 10 '10 at 14:40

1

@BalusC: downloading a javascript file blocks all other downloads, regardless of domains. Also, defaults are too entrenched to rely on users changing them ;)
–
voyagerMay 10 '10 at 14:42

And the creator of YSlow, which you linked too, states that you can accomplish asynch JS download's - stevesouders.com/blog/2009/04/27/… However, given my requirement that both Gmaps and JQuery need to be downloaded first, I'm not sure how to use Steve's example. As such, I don't believe you answer is correct.
–
TeddykMay 10 '10 at 14:43

@Teddyk: I'd use DOM injection, as all other workarounds seem even hackier, and more prone to get you more problems with cross browser support.
–
voyagerMay 10 '10 at 14:47

@voyager, but how do you create an event that can be fired once BOTH (google-maps and jquery) are downloaded before executing the inline JS code if using DOM injection? Make sense what I'm saying? Again, as a reminder - my page can't render until both Gmaps and Jquery have downloaded. What I'm trying to do is simply speed up the download process since my page had a hard dependency on those two files.
–
TeddykMay 10 '10 at 14:49

But what would my callback function be if I need to wait until 2 JS files have been downloaded?
–
TeddykMay 10 '10 at 17:12

The callback is triggered after all the URLs in the array have been loaded. If you put two URLs in that array, the callback will be triggered after both of them have loaded. There may be more complex cases, but I do not pretend that I have offered an exhaustive solution. It is merely a starting point for your needs.
–
Ionuț G. StanMay 10 '10 at 18:37

Someone asked me to comment on this thread, but that was before @lonut posted a response. @lonut's code is a very good solution, but I have some comments (critical and not so critical):

First, @lonut's code assumes that the scripts do NOT have load dependencies on the other scripts. This is a little hard to explain, so let's work with the simple example of jquery.min.js and prototype.js. Suppose we have a simple page that just loads these two scripts like this:

Remember - there's nothing else in the page - no other JavaScript code. If you load that page the two scripts get downloaded and everything's fine. Now, what happens if you remove the jquery.min.js script? If you get errors from prototype.js because it's trying to reference symbols defined in jquery.min.js, then prototype.js has a load dependency on jquery.min.js - you cannot load prototype.js unless jquery.min.js has already been loaded. If, however, you don't get any errors, then the two scripts can be loaded in any order you wish. Assuming you have no load dependencies between your external scripts, @lonut's code is great. If you do have load dependencies - it gets very hard and you should read Chapter 4 in Even Faster Web Sites.

Second, one problem with @lonut's code is some versions of Opera will call loadCallback twice (once from the onload handler and a second time from the onreadystatechange handler). Just add a flag to make sure loadCallback is only called once.

Sounders, I'm extremely honored to have you comment on my post. With that being said, is there a solution to my question? In case it help, I have posted a 2nd question that is directly related to this problem at stackoverflow.com/questions/2804494/… that might provide you some more detail. Again, many thanks and I overwhelmed that you're on StackOverlow :)
–
TeddykMay 10 '10 at 18:02

Indeed, I have intentionally ignored the first issue, as in my opinion it can be solved by issuing another call to require inside the callback. Haven't done any tests, but seems like it should work. Regarding the second issue, I knew there were some browsers in which the callback would trigger twice, but couldn't trigger the bug as I have the latest Opera version (and IE6 worked fine). Anyway, thanks for the feedback!
–
Ionuț G. StanMay 10 '10 at 18:45

In either case, LABjs will download all of the scripts ("jquery.js", "googlemaps.js", and "plugin.jquery.js") in parallel, as least up to the point the browser will allow. But by judicious use of the .wait() in the chain, LABjs will make sure they execute in the proper order. That is, if there's no .wait() in between the two scripts in the chain, they will each execute ASAP (meaning indeterminate order between tehm). If there's a .wait() in between two scripts in the chain, then the first script will execute before the second script, even though they loaded in parallel.

Here is how I've managed to load gmaps asynchronously on a jquery mobile:
First, you can load jquery (i.e. with the require function posted above by Ionuț G. Stan)
Then you can make use of the callback param in gmaps to do the following:

Regardless what order they download in, the scripts should be parsed/executed in the order in which they occur on the page (unless you use DEFER).

So, you can put both Google Maps first in the head, THEN JQuery. Then, in the body of your page somewhere:

<script language="Javascript">
function InitPage() {
// Do stuff that relies on JQuery and Google, since this script should
// not execute until both have already loaded.
}
$(InitPage); // this won't execute until JQuery is ready
</script>

But this does have the disadvantage of blocking your other connections while loading the beginning of the page, which isn't so awesome for page performance.

Instead, you can keep JQuery in the HEAD, but load the Google scripts from the InitPage() function, using JQuery's Javascript-loading functionality rather than the Google JSAPI. Then start your rendering when that call-back function executes. Same as the above, but with this InitPage() function instead:

Would this still be asych? Since it appears to no start downloading the Google Maps until JQuery downloads first.
–
TeddykMay 10 '10 at 15:44

True, but JQuery is a fast load. The solution above solves the dependency problem, not async network connections. You can use the document.write hack at the top to start async loading of JQuery and Google, and try using DEFER on your main page code, but that won't guarantee that your main script will wait on the other scripts. To do that, you'll need your own "ready" function that tests for the JQuery and Google Maps objects, waits a few milliseconds and tries again if they aren't both available, and times out with an appropriate error if they don't load in a reasonable time period.
–
richardtallentMay 10 '10 at 19:52

Move your javascript includes (<script src="...) from the HEAD element to the end of your BODY element. Generally whatever is placed in the HEAD is loaded synchronously, whatever is placed in the BODY is loaded asynchronously. This is more or less true for script includes, however most browsers these days block everything below the script until it is loaded - hence why having scripts included at the bottom of the body is best practice.

This is also the reason why stylesheets should be in the head, and javascript should be in the body. As we do not want to see our page turn from spaghetti to niceness while the styles load asynchronously, and we don't want to wait on our javascript while our page loads.