I have 3 scripts that need to execute in order where each next script waits for the previous script to finish executing. Is there a faster more elegant way to write this?
Say for example I had a production html page that needed to load 20 scripts in order.
note: adding defer to each script does not execute the scripts sequentially.
Here is a working example:
index.html
<html>
<head>
<title>Load scripts in order</title>
<script>
const scripts = ["script1.js", "script2.js", "script3.js"]
for (let i = 1; i < scripts.length; i++) {
document.head.addEventListener(scripts[i - 1], () => {
console.log(`finished processing ${scripts[i - 1]}`)
const nextScript = document.createElement("script")
nextScript.src = scripts[i]
document.head.appendChild(nextScript)
})
}
</script>
<!--load our first script to start sequential loading-->
<script src="script1.js"></script>
</head>
<body>
<h1>Hello world</h1>
</body>
</html>
script1.js
const foobar = async () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, 3000)
setTimeout(() => {
reject(new Error("did not finish in time."))
}, 10000);
})
}
foobar().then(() => {
console.log("finished loading script1.js")
document.head.dispatchEvent(new Event("script1.js"))
} )
script2.js
const foobar2 = async () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, 3000)
setTimeout(() => {
reject(new Error("did not finish in time."))
}, 10000);
})
}
foobar2().then(() => {
console.log("finished loading script2.js")
document.head.dispatchEvent(new Event("script2.js"))
} )
script3.js
console.log("hello world")
stack trace:
finished loading script1.js
finished processing script1.js
finished loading script2.js
finished processing script2.js
hello world
you will need to use for loop that support async and await for (const script of scripts)
sample is below
<html>
<head>
<title>Load scripts in order</title>
<script>
async function loadScript(src) {
return new Promise((resolve, reject) => {
const script = document.createElement("script");
script.src = src;
script.onload = resolve;
script.onerror = reject;
document.head.appendChild(script);
});
}
async function loadScriptsSequentially(scripts) {
for (const script of scripts) {
console.log(`Loading script: ${script}`);
await loadScript(script);
console.log(`Finished loading script: ${script}`);
}
}
const scripts = ["script1.js", "script2.js", "script3.js"];
loadScriptsSequentially(scripts);
</script>
</head>
<body>
<h1>Hello world</h1>
</body>
</html>