Reputation: 9891
In the JS library I am writing, I have this loadScript
func:
function loadScript(src, callback) {
var script = document.createElement('script');
script.src = src;
// script.type = "text/javascript";
// script.async = false;
if (typeof callback !== 'undefined') {
script.onload = function () {
callback();
};
}
document.head.appendChild(script);
}
Inside the main js file, I use it to load the dependencies dynamically after the main js file is loaded, initiate the JSLib
object in its callback.
loadScript(baseUrl + '/dependencies/you-load-me-long-time.js', function() {
window.JSLib = true;
}
Then I have a web page that calls this library.
var jsLib = new JSLib({...});
The problem that I encounter is that - in the web page that loads this JS library, the browser complains that the JSLib
is not defined because the dependency file you-load-me-long-time.js
has not finished loading yet when the script in the web page is executed.
A work-around that seems to be working for now is that, in the web page, I wrap the initiation code in a $(window).load(function() {});
call.
Is there any way that I can overcome this timing issue? ex: "blocking" the loading of the rest of the web page until JSLib is loaded (doesn't sound like a good idea anyway), etc...
Upvotes: 0
Views: 136
Reputation: 707706
There are only two ways to create blocking dynamic script loaded via JS and both are fairly undesirable.
If the document is still being parsed, you can use document.write()
to insert a <script>
tag at the current document location. That will then be parsed and loaded synchronously.
If the script resource is on the same origin as the document, you can fetch the script with a synchronous Ajax call and then eval the script.
Since neither of these is particularly desirable, the usual work-around is to surface a callback all the way back to the caller of the script so that they can participate in when the async operation is done and put their code in that async callback.
var jsLib = new JSLib({...}, function() {
// put code here that uses the jsLib because now it is loaded
});
For this messy reason, it is usually not a good practice to make the completion of a constructor be an async operation. It significantly complicates the use of the object.
More common would be to let the constructor just create the shell of the object and then require a .load(fn)
method call to actually load it. This will likely lessen the chance of callers misuing the library.
var jsLib = new JSLib({....});
jsLib.load(function(err) {
if (err) {
// error loading the library
} else {
// library is loaded now and all functionality can be used
}
});
FYI, your idea to use $(window).load()
is not a good idea. That method may accidentally work just because it delays the timing enough until your script happens to be loaded, but the window load event does not specifically wait until dynamically loaded scripts have been loaded so it is not a reliable way to wait for your script.
Upvotes: 1