loading a js file asynchronously from a js file that loads asynchronously - javascript

I had a javascript file(initial.js) on the page inserted through the script tag like so:
<script src="initial.js"></script>
This file creates dom elements(let say two links) and also loads another jQuery plugin(plugin.js) asynchronously via jQuery ajax method. Clicking on those two links brings up a module from the jQuery plugin(plugin.js).
The javascript file(initial.js) was then modified to load asynchronously on the page via jQuery ajax instead of via script tag. This has resulted in some events not getting attached to the links intermittently and this results in the plugin not being called.
I believe the browser is loading the async scripts in its own order and hence the links fail to launch the plugin intermittently. Any pointers to resolve this issue with this new set up?

At a high-level, I think you need to look into something like require.js. Alternatively, you could look into some jQuery event handling code which allows you to listen on load events of calls which may help you determine when one script loaded before loading the next one.

You have probably tried something like this in the past:
var output;
$.get('data.php',function(data){
output=data;
});
alert(output);
You will get an undefined error because Javascript doesn't wait around for the AJAX call to be returned before moving onto the next code.
Same thing goes for scripts. If you place multiple calls to multiple scripts, you will probably get the smallest one returned the quickest, and that script executed. If you load a script that is 10kb and then one that is 1kb, the 1kb script will probably return the quickest and then be executed even though it was called after the 10kb script.
To correct this, you could make a queue system and then only load each script after the previous has loaded:
var scripts=['script1.js','script2.js','script3.js'];
$(document).ready(function(){
loadScript();
});
function loadScript(){
if(sendQueue.length==0)
return;
$.getScript(scripts[0],function(){
scripts=scripts.slice(1);
loadScript();
});
}
But if you are loading scripts from within scripts from within scripts... very Inception like, then this still may not work.

Related

Get progress of script tag evaluation?

I have a large javascript from a webpack build being loaded as such:
<script src="application.bundle.js"></script>
I want to add a progress bar while the script loads. In chrome dev tools timeline, I can see that most of the load time is spent here: "Evaluate Script", understandably so. Is there any way to get progress or at the very least a done event to know when the script is done evaluating?
I could do something in the application script like window.appLoaded = true and look for that periodically. Is there a way to do this without modifying the application script?
If you want a callback after the file is loaded, I suggest you load it asynchronously with a function call that uses a callback function upon completion.
You could put up a progress spinner before calling the loader function, with the callback taking it down. Something like this:
function myLoadScript( ) {
showMyProgress();
loadScript( 'application.bundle.js', hideMyProgress );
}
This page shows a few ways to load scripts asynchronously. A generic loadScript() function is shown there.

Best way to delay js loading?

I'm using a bootstrap theme that requires a few javascript files. On some of my pages I load quite a bit of content from the server which means not all the html will be on the page at the time the javascript files are evaluated.
This prevents the event handlers from binding to the html that's loaded after the javascript is evaluated. So far I've fixed the problem by loading the scripts after the ajax call is finished, but this seems pretty hokey to me. Here's my function:
$.get("/path/to/rest/call", function(data) {
$('#htmlElement').html(data);
}).done(function() {
$.getScript("/path/to/js/file.js");
});
I feel like there's a better way to do this. Is there?
There may be a cleaner way of solving this than dynamically loading the metroui library. It looks like it depends upon jQuery's .ready() to know when the page is loaded and when it can initialize it's things. But, that doesn't work for you because you are dynamically loading content via Ajax.
What you can do is you can hold off the jQuery ready() notification until after your ajax content is loaded. This will then hold off the firing of metro's initialization until after your dynamic content is loaded. This would allow you to load metro in a stock <script> tag in the <head> section like their doc suggests. The way this works is you add this to the <head> section, after jQuery is loaded:
<script>
jQuery.holdReady(true);
</script>
Then, after your ajax code has succesfully completed, you do this (from the success handler, after you've put your new content into the page):
jQuery.holdReady(false);
which then releases jQuery to call it's .ready() handlers and metro will do it's thing after your content is loaded.
See jQuery doc for jQuery.holdReady(...).

Head js Problems with loading javascript files

I'm using Head js to load my javascript files in parallel. I added head js to my head and then used head.js("path/to/file/my.js"); but when I load my webpage the script is missing. Only after refreshing a few times does the whole script work properly. Why do I need to refresh it to make it work? Any suggestions would be appreciated!
As the scripts are loaded asynchronously, you can't use it immediately. After you have refreshed the page, it will find the script in the cache, so it will load in time for any code needing it sometimes.
Use the ready method for any code that needs the script:
head.ready(function() {
// any code that needs the script to be loaded first
});
Another way is to mark your library and then get the ready event when your script is loaded. Read more from http://headjs.com/ Labeling scripts.
head.ready("your", function() {
});
head.js(
{jquery: "http://http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"},
{tools: "http://cnd.jquerytools.org/1.2.5/tiny/jquery.tools.min"},
{your: "http://a.heavy.library/we/dont/want/to/wait/for.js"},
// label is optional
"http://can.be.mixed/with/unlabeled/files.js"
);

Inserting a script dynamically in the DOM

I'm trying to understand why this code doesn't work and the alert output is just blank.
<script type="text/javascript">
(function() {
...
var s = document.getElementsByTagName('script')[0]; alert(s.innerHTML);
s.parentNode.insertBefore(res, s);
...
})();
</script>
It should add res before s if I'm not wrong. That's what I specifically need, as I tried to append it to body and it's added successfully (after doing that though I have to run some code inside this function, so if the script is not loaded before it, such code will error).
This function should run when document is loaded or is that the problem? In particular, the getElementsByTagName function seems to not return anything.
Thanks to everyone.
You cannot run this type of code before the document is loaded. This code has to be loaded before it can be run (see the circular argument here). And, by then, much of the rest of the document has been loaded. You can dynamically load scripts AFTER the document has been loaded. If you need a script loaded before other scripts, then you either have to put them all in the document statically in the order you need them to be run or you need to add them all dynamically in the order you need them to run and you will need to keep track of completion of one load before loading the next.
If you care to describe the broader problem you're trying to solve, we can probably suggest a more elegant solution than what you are pursuing.

Question about when a script is executed after appending it

In my code, I have javascript that dynamically adds another script to the page:
created_script=document.createElement('script');
created_script.src='other_script';
created_script.type='text/javascript';
document.head.appendChild(created_script);
in this 'other script', I have a function called reloader().
The problem I'm having is that right after I dynamically add the script, I try to call the function reloader(), but I'm getting a reloader is not defined error.
Here's is like what I am doing:
created_script=document.createElement('script');
created_script.src='other_script';
created_script.type='text/javascript';
document.head.appendChild(created_script);
reloader();
Can someone explain to me why this doesn't work and how should I fix this so that reloader() can be called after appending the script in a single dynamic call (if possible at all)?
Loading scripts like this happens asynchronously. This means that at the time you call reloader(), the external script may still be loading.
Your script shouldn't invoke loader() until it knows that the external script has completely loaded. See this related question: How can I delay running some JS code until ALL of my asynchronous JS files downloaded?

Categories

Resources