我有 3 个脚本需要按顺序执行,其中每个下一个脚本都会等待上一个脚本完成执行。有没有更快更优雅的方式来写这个?
举例来说,我有一个生产 html 页面,需要按顺序加载 20 个脚本。
注意:为每个脚本添加 defer 不会按顺序执行脚本。
这是一个工作示例:
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")
堆栈跟踪:
finished loading script1.js
finished processing script1.js
finished loading script2.js
finished processing script2.js
hello world
您将需要使用允许异步和等待的 for 循环,示例如下
<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>