重新再來一次吧!回頭看一下〈載入、運行 WebAssembly〉,無論是 Fetch,或者是 WebAssembly 的 instantiateStreaming
等函式,都傳回了 Promise
,許多文件也是這麼介紹模組的載入、實例化等過程。
別忘了,在 ECMAScript 7 中納入了 async
、await
,這表示在瀏覽器支援的情況下,是可以運用 async
、await
來令這個過程更為直覺而容易撰寫!
接下來的內容,可以用來與〈載入、運行 WebAssembly〉中的範例做個對照。
例如,就這個簡單的 WebAssembly 來說:
(module
(func $add (param $lhs i32) (param $rhs i32) (result i32)
get_local $lhs
get_local $rhs
i32.add)
(export "add" (func $add))
)
使用 async
、await
,來實作載入、實例化模組並呼叫函式的過程,可以寫為:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<script>
(async () => {
const wasm = fetch('program.wasm');
const {instance} = await WebAssembly.instantiateStreaming(wasm);
console.log(instance.exports.add(1, 2));
})();
</script>
</body>
</html>
若沒有需要獲取 Module
實例,使用 ES6 解構語法直接取得 Instance
是很方便的做法,就整個流程的效率來說,這也是建議的寫法!
WebAssembly.instantiateStreaming
會透過傳入的 Promise
取得儲存著 .wasm 的 ArrayBuffer
,然後再進行實例化,因此上例相當於:
(async () => {
const resp = await fetch('program.wasm');
const wasm = await resp.arrayBuffer();
const {instance} = await WebAssembly.instantiate(wasm);
console.log(instance.exports.add(1, 2));
})();
如果想要 WebAssembly.Module
的實例,可以使用 WebAssembly.compileStreaming
,例如:
(async () => {
const module = await WebAssembly.compileStreaming(fetch('program.wasm'));
// 也許用 module 做點其他的事....
// Bla...bla..
// 這是個阻斷操作
const instance = new WebAssembly.Instance(module);
console.log(instance.exports.add(1, 2));
})();
因為 new WebAssembly.Instance(module)
會是個阻斷操作,如果沒必要取得 Module
實例,就建議不用如上撰寫了。
實際上,WebAssembly.compileStreaming
會取得 ArrayBuffer
,然後使用 WebAssembly.compile
來編譯、生成 Module
實例,也就是上例相當於:
(async () => {
const resp = await fetch('program.wasm');
const wasm = await resp.arrayBuffer();
const module = await WebAssembly.compile(wasm);
// 也許用 module 做點其他的事....
// Bla...bla..
// 這是個阻斷操作
const instance = new WebAssembly.Instance(module);
console.log(instance.exports.add(1, 2));
})();
若手中已經有個 ArrayBuffer
,也可以用來建構 WebAssembly.Module
實例:
(async () => {
const resp = await fetch('program.wasm');
const wasm = await resp.arrayBuffer();
// 這是個阻斷操作
const module = new WebAssembly.Module(wasm);
// 這是個阻斷操作
const instance = new WebAssembly.Instance(module);
console.log(instance.exports.add(1, 2));
})();
如果想要善用 JavaScript 非同步的特性,就要留意一下阻斷操作的部份是否真的是必需的!