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