[英]Trying to understand Javascript script execution order. Tried async, defer, dynamically loading scripts and all have unpredictable results
我有以下代碼,根據代碼我假設操作的順序是:
然而,事實並非如此。 在 sleep 命令完成之前,瀏覽器中不會顯示/更新任何內容。 在控制台中,在“ONE start”之前記錄了“SLEEP start”。
我嘗試在調用 loadScript 時啟用異步,我已經將 sleep 命令移到了 two.js 中。 沒有什么變化。 我在這里想念什么? 我將如何更改我的代碼以實現正確的下載和執行?
這是我的代碼:
html:
<!doctype html>
<html lang="en">
<body>
<div id="div1" style="background-color: orange;">
</div>
<script>
function sleep(milliseconds) {
const date = Date.now();
let currentDate = null;
do {
currentDate = Date.now();
//console.log('sleep is executing');
} while (currentDate - date < milliseconds);
}
function loadScript(src, async_enabled = async_enabled) {
let script = document.createElement('script');
script.src = src;
script.async = async_enabled;
document.body.append(script);
}
loadScript("one.js", async_enabled = false);
console.log('SLEEP start');
sleep(8000);
console.log('SLEEP stop');
loadScript("two.js", async_enabled = false);
loadScript("three.js", async_enabled = false);
</script>
</body>
</html>
一個.js:
console.log('ONE start');
let one = document.getElementById('div1');
let p1 = document.createElement('p');
p1.innerHTML = 'One';
one.appendChild(p1);
console.log('ONE stop');
二.js:
console.log('TWO start');
let two = document.getElementById('div1');
let p2 = document.createElement('p');
p2.innerHTML = 'Two';
two.appendChild(p2);
console.log('TWO stop');
three.js:
console.log('THREE start');
let three = document.getElementById('div1');
let p3 = document.createElement('p');
p3.innerHTML = 'Three';
three.appendChild(p3);
console.log('THREE stop');
更新我只是使用 sleep 命令來幫助我了解 js 腳本是如何加載和執行的(順序)。 我真的不想在我的代碼中使用 sleep 命令。 我將 html 更改為:
<!doctype html>
<html lang="en">
<body>
<div id="div1" style="background-color: orange;">
</div>
<script>
function sleep(milliseconds) {
const date = Date.now();
let currentDate = null;
do {
currentDate = Date.now();
//console.log('sleep is executing');
} while (currentDate - date < milliseconds);
}
function loadScript(src, async_enabled = async_enabled) {
let script = document.createElement('script');
script.src = src;
script.async = async_enabled;
document.body.append(script);
}
loadScript("one.js", async_enabled = false);
</script>
</body>
</html>
將 one.js 更改為:
console.log('ONE start');
let one = document.getElementById('div1');
let p1 = document.createElement('p');
p1.innerHTML = 'One';
one.appendChild(p1);
console.log('ONE stop');
loadScript("two.js", async_enabled = false);
並將 two.js 更改為:
console.log('TWO start');
sleep(5000);
let two = document.getElementById('div1');
let p2 = document.createElement('p');
p2.innerHTML = 'Two';
two.appendChild(p2);
console.log('TWO stop');
我仍然得到相同的結果。 我知道我應該理解為什么會發生這種情況,但我還沒有明白。 那么如何更改代碼以使 one.js 中發生的事情立即顯示在瀏覽器中?
您的sleep
是忙碌的睡眠,由於各種原因,這是一個壞主意。 尤其是在瀏覽器中的 JavaScript 中,所有內容都有效地以單線程運行。 這意味着當您的代碼處於“睡眠”狀態時,不會執行涉及 JavaScript 的任何其他內容。
您的loadScript
方法將一個新元素附加到 DOM,這會立即發生。 在當前的 JavaScript 運行完成之前無法開始執行新腳本,這就是為什么所有通過loadScript
加載的腳本只有在您睡眠后才會開始運行。
解決此問題的正確方法是在瀏覽器中采用 JavaScript 的事件驅動性質,而不是嘗試在繁忙的循環中“保持運行”。
如果您想“睡覺”,您只需安排新代碼稍后運行並從調用中返回。
順便說一句,這也會釋放 JavaScript 事件循環來處理諸如加載其他腳本之類的事情。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.