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 外壳会生成后者。

异步何时不异步?

脚本 异步的两种常见情况(如 HTML 规范所定义)是

html
<script async>
  code();
</script>

js
const script = document.createElement("script");
script.textContent = "code()";
document.body.appendChild(script);

两者都被视为 '内联' 脚本,并立即进行编译和运行。

如果您的代码在 JS 字符串中?您应该使用具有对象 URL 的 Blob,而不是使用 evalinnerHTML,这两者都会触发同步编译

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 是使此脚本异步的原因。