I use an include function to dynamically include javascript files/headers/libraries.
The problem is that it seems loading the file happens in a multi-threaded way (tested on Chrome v102) and the js file is not yet loaded when I immetiately use functionnality after that.
Example with jQuery:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8"/>
<script type="text/javascript">
var include_once = function(url) {
/*
[additional code to check if 'url' was already included]
*/
var script = document.createElement("script");
script.type = "text/javascript";
script.src = url;
document.head.appendChild(script);
}
include_once("https://code.jquery.com/jquery-3.6.0.min.js");
</script>
</head>
<body>
<script type="text/javascript">
/*
ok if I wait 'long enough' but is arbitrary
*/
setTimeout(function(){
$(document).ready(function(){
console.log("ready (timeout)");
});
}, 10);
/*
how to wait until window.$ is defined?
*/
$(document).ready(function(){
console.log("ready");
});
</script>
</body>
</html>
This code will likely give you a $ is not defined
error, and ready (timeout)
will be logged to the console.
How can I make my script wait until window.$ !== undefined
here ?
I tried while(window.$ === undefined) {}
but it completely blocks the script and $
is never defined.
you can promisfy the loading process, by creating a promise on first script and then on the second script check if the promise is resolved.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8"/>
<script type="text/javascript">
var isLoaded = new Promise((res,rej) => {
function include_once(url) {
/*
[additional code to check if 'url' was already included]
*/
var script = document.createElement("script");
script.type = "text/javascript";
script.onload = () => res()
script.onerror = () => rej()
script.src = url;
document.head.appendChild(script);
}
include_once("https://code.jquery.com/jquery-3.6.0.min.js");
})
</script>
</head>
<body>
<script type="text/javascript">
isLoaded.then(() => {
$(document).ready(function(){
console.log("ready");
});
})
</script>
</body>
</html>