asm.js 的非同步指令碼
每個中型或大型遊戲都應該將 asm.js 程式碼作為非同步指令碼的一部分進行編譯,以賦予瀏覽器最佳化編譯過程的最大靈活性。在 Gecko 中,非同步編譯允許 JavaScript 引擎在遊戲載入時在主執行緒之外編譯 asm.js,並快取生成的機器程式碼,以便在後續載入時無需重新編譯(自 Firefox 28 起)。要檢視區別,請在 about:config 中切換 javascript.options.parallel_parsing。
讓非同步發揮作用
實現非同步編譯非常簡單:在編寫 JavaScript 時,只需像這樣使用 async 屬性
html
<script async src="file.js"></script>
或者,透過指令碼實現相同的功能
js
const script = document.createElement("script");
script.src = "file.js";
document.body.appendChild(script);
(透過指令碼建立的指令碼預設設定為 async。)Emscripten 生成的預設 HTML shell 會產生後者。
何時非同步不是非同步?
根據 HTML 規範的定義,以下兩種情況指令碼不是非同步的:
html
<script async>
// Inline JavaScript code
</script>
and
js
const script = document.createElement("script");
script.textContent = "// Inline JavaScript code";
document.body.appendChild(script);
這兩種情況都被視為“內聯”指令碼,會立即進行編譯和執行。
如果您的程式碼在 JS 字串中怎麼辦?請使用 Blob 和物件 URL,而不是使用 eval 或 innerHTML,因為這兩者都會觸發同步編譯:
js
const blob = new Blob([codeString]);
const script = document.createElement("script");
const url = URL.createObjectURL(blob);
script.onload = script.onerror = () => URL.revokeObjectURL(url);
script.src = url;
document.body.appendChild(script);
透過設定 src 屬性而不是使用 innerHTML,使得該指令碼是非同步的。