Get progress of script tag evaluation? - javascript

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.

Related

Loading your JavaScript after an external JS get executed

I've a problem that is a bit tricky over here, I'm trying to apply a simple JQuery line of code that addClass to a div with class pop-up
but the problem is that class pop_up is not accessible after jQuery(document).ready(function($){});
This class is actually added from an external JS and the pop_up functionality
is also added from an external JS so I'm wondering
How To Add The Class using JQuery after the external JS get executed so pop_up class can be found using:
$('.pop_up');
What I've tried:
jQuery(document).ready(function($) {
$('.pop_up').addClass('importantRule');
$('.pop_up').toggleClass('importantRule');
});
this is not working as the external JS added the class somehow after .ready, so if you tried to print out $('.pop_up') it will be undefined.
I've also tried to look for the class using a constant class container of div.pop_up like this:
$('div.element').find('.pop_up').addClass('importantRule');
that didn't work either, I know for a fact the problem is with calling the function in .ready as some how the external JS get executed after it so,
is there away around this?
if not, is there a way to detect if all of external JS files are ready and loaded?
You can have $(document).ready() multiple times in a page. The code gets run in the sequence in which it appears.
You can use the $(window).load() event for your code since this happens after the page is fully loaded and all the code in the various $(document).ready() handlers have finished running.
$(window).load(function(){
//your code here
});
One way is to use a setTimeout to check:-
function checkForElement() {
setTimeout(function() {
if ($('.pop_up').length) {
$('.pop_up').addClass('importantRule');
} else {
checkForElement();
}
}, 100);
}
checkForElement();
This will wait for 100ms, then check. if its not there then it will wait again, and again, etc.
You experience a race condition. If the external script finishes running first, then your code will work, but if your code finishes first, then it breaks.
You can either hack around it like Satej S suggested on the comments, and give a reasonable timeout which will make sure the external script finished running, and after that timeout, run your script.
setTimeout(function(){ doSomething(); }, 3000);
A better solution will be using a callback from the external script (can you edit the external script?). This way, the second the external script ends, it calls for one of your internal functions that will start working.
To avoid timeouts that most other answers suggest, I would advise you to try adding "defer" tag to your script include. That way the script trying to add class "importantRule" will wait until all of the other scripts have been loaded and executed.
In addition, I found this question quite similar
load and execute order of scripts
Hope this helps! Thanks

onLoad function not executing

I'm trying to set up a demo page for an API I'm developing at work, but I can't get my JavaScript to work. The JavaScript should poll on my server to check if the elaboration has ended and then perform the necessary operations to get the result on the browser, but I keep getting this error:
Failed to clear temp storage: It was determined that certain files are unsafe for access within a Web application, or that too many calls are being made on file resources. SecurityError
After the first time I decided to simplify my code, cutting off calls until I got it working and the add up. Currently my function looks like this, but I still get the same error (I cleared the browser's cache, so it is not executing old versions):
function getStatus(){
window.alert("Prova");
}
It should execute when a div is loaded:
<div id="LoaderImage" onload="getStatus()">
...
</div>
Since I can see the loading gif inside the div I am sure the div is being loaded, but the function doesn't do anything anyway.
The JavaScript and jQuery code used inside my template works fine, so the main suspect for the error is this function, which is the only one which does not work.
Use onload on body instead. I would prefer to invoke it on the window object like this,
window.onload = getStatus;
or to use it on <body> .. </body> do this:
<body onload="getStatus()">
...
</body>

When is requireJS done loading all modules

I'm wanting to wait for all of my requireJS modules to finish loading before firing an event.
Is there an event, or a way to listen for all of my requireJS modules to finish loading?
The details:
I'm trying to add custom dimensions to my Google Analytics, and then send a pageview. This is easy to do on all pages if I set the same dimensions but in some of my requireJS modules I want to change the dimensions BEFORE the page view.
I've got my template javascript which is run on every single page, I want it to do:
LISTEN_FOR_MODULES_TO_LOAD(function() {
$(document).trigger('set-your-analytics-dimensions-yall');
ga('send', 'pageview');
});
Then on some of my subpages I've got modules doing:
$(document).on('set-your-analytics-dimensions-yall', function() {
ga('set', 'dimension');
});
I want the flow to be:
Listen for all my modules to finish loading
Ask other modules to set their dimensions and other values
Set pageview
The problem is that I have no way to listen for all my requirejs modules to load.
Things I've considered:
DOM Ready
This doesn't work because DOM Ready can fire before or after all JavaScript modules are loaded.
window.onload
This isn't reliable and can fire multiple times. If an image is added to the page 10 minutes later it can fire again. If an external resource never loads this event will never fire.
Is there an options I have missed? Or something I have missed entirely from requireJS?
This question is over two years old, but it was the only relevant question I found on SO when I had the same problem. I eventually found an answer that works for me. Here's some background: I have a dynamically generated page, with multiple and varied numbers of page sections that may include modules loaded by require.js. Picture a page with a variable number tiles for example, and each tile may load scripts using require. Now when all tiles are loaded, I want to run some other javascript. But how do you tell when require.js is done loading everything, including modules that may be loaded as sub modules?
Looking at the require.js code, I see that it contains a registry, which appears to be a list of pending loads and their callbacks. So when the registry is empty, require.js is done loading and done running callbacks. At least it appears that way, and this works for me. Basically at the bottom of the page (below any other calls to require()), I add this javascript:
function run_final_action($) {
if ($.isEmptyObject(require.s.contexts._.registry)) {
do_final_action();
}
else {
setTimeout(run_final_action, 100);
}
}
require( ['jquery'], function ($) { run_final_action($) } );
Here I am using jquery because I already have it loaded in the page, but it isn't really necessary. The basic idea is just to check the registry for the default context in requirejs (named "_") and when it is empty, that means requirejs has no pending scripts to load or callbacks to run. This works for my use case anyway.

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

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.

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