I am probably making a rookie mistake.
Goal
I have a script loader.js
, where I want to supply a set of javascript files intended to manage component shape, size, position, etc.
The file is like this:
const loadScript = (FILE_URL, async = true, type = "text/javascript") => {
return new Promise((resolve, reject) => {
try {
const scriptEle = document.createElement("script");
scriptEle.type = type;
scriptEle.async = async;
//scriptEle.async = false; // i tried with this line as well.
scriptEle.defer = true;
scriptEle.src =FILE_URL;
scriptEle.addEventListener("load", (ev) => {
resolve({ status: true });
});
scriptEle.addEventListener("error", (ev) => {
reject({
status: false,
message: `Failed to load the script ${FILE_URL}`
});
});
document.body.appendChild(scriptEle);
} catch (error) {
reject(error);
}
});
};
$(document).ready(function () {
setTimeout(proceed, 1); // wait for the document to be fully ready.
});
async function proceed() {
await loadVars(); // Load variable definitions
await loadComponents(); // load component definitions
await make_components(); // and populate them
}
function make_components() {
switch (monitorType) { // monitor type should be defined once loadvar executes (and console.log agrees)
case 1 :
addMobileHeader(wfull, hfull * 0.1);
addMobileHeroBlock(wfull, hfull* 0.7);
break;
}
}
function loadVars() {
loadScript("variables.js").then( data => {
console.log("Variables: Script loaded successfully", data);
})
.catch( err => {
console.error(err);
});
}
function loadComponents() {
loadScript("components_mobile.js").then( data => {
console.log("Components (mobilephone): Script loaded successfully _ mobile", data);
})
.catch( err => {
console.error(err);
});
loadScript("components_wide.js").then( data => {
console.log("Components (widescreen):Script loaded successfully _ wide", data);
})
.catch( err => {
console.error(err);
});
}
Problem
Of course, make_components()
is triggered before loadVars
completes execution.
Attempt to solution
Inspired from this answer,I thought that since variables.js
is added first, it will be executed first, before the next (deferred) file, components_mobile.js
is loaded and executed.
And only after all that is done, then the make_components
function will execute, and will find all the definitions in loadVars
file.
I know that I can make a call the next function directly in the .then
part, like
loadScript("variables.js").then( data => {
console.log("Variables: Script loaded successfully", data);
//call next function here
})
But that will create a hell of chained function very hard for me to debug.
Question
Is there a way i can force the JS engine in chrome/ firefox to wait while one script is fully loaded and executed? Thank you.
EDIT : Without third party libraries, if possible please.
3
Answers
Thanks to @Nicholas Tower. Indeed, the return promise is a good idea.
I asked chatGPT, and chatGPT gave this solution which is very close to Nicholas Tower.
Define the loader function:
Then Invoke the loader function :
note, that each call to
loadScript
itself is wrapped in another function. In order to achieve that multiple-wrapping, chatGPT says, that you need to make each layer of wrap an async function, and each wrapped function an await.Then :
async function make_components() {
}
This works fine.
Try to do this:
Your
loadVars
andloadComponents
are implicitly returningundefined
, soawait loadVars()
andawait loadComponents()
don’t actually wait for anything. You’ll need to return a promise.If you prefer
.then
syntax, do:If you prefer
async
/await
, do:And make a similar change in loadComponents