Let's review Loading and running WebAssembly, Some functions in Fetch and WebAssembly API, such as instantiateStreaming
, return Promise
. You use then
methods to handle async operations like synchronous styles.
ECMAScript 7 provides async
and await
. If your browsers support ES7, you can use them to work with promises in a more comfort fashion.
For comparison, the following examples will show how to use async
and await
to do things like examples in Loading and running WebAssembly.
If you have a simple module:
(module
(func $add (param $lhs i32) (param $rhs i32) (result i32)
get_local $lhs
get_local $rhs
i32.add)
(export "add" (func $add))
)
Using async
and await
to load, instantizate the module and invoke the exported function can be written as follow.
<!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>
It's the recommended way if the Module
instance is not required.
WebAssembly.instantiateStreaming
would take out the ArrayBuffer
instance of “.wasm“ from the Promise
object and instantiate the module. The following code has the same effect as the above.
(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));
})();
If the instance of WebAssembly.Module
is required, you may use WebAssembly.compileStreaming
. For example:
(async () => {
const module = await WebAssembly.compileStreaming(fetch('program.wasm'));
// use module to do things....
// Bla...bla..
// block the main thread until it completes
const instance = new WebAssembly.Instance(module);
console.log(instance.exports.add(1, 2));
})();
new WebAssembly.Instance(module)
would block the main thread until it completes so don't do this if WebAssembly.Module
is required.
In fact, WebAssembly.compileStreaming
will take out the ArrayBuffer
and use WebAssembly.compile
to compile it to a WebAssembly.Module
instance. The following code has the same effect as the above.
(async () => {
const resp = await fetch('program.wasm');
const wasm = await resp.arrayBuffer();
const module = await WebAssembly.compile(wasm);
// use module to do things....
// Bla...bla..
// block the main thread until it completes
const instance = new WebAssembly.Instance(module);
console.log(instance.exports.add(1, 2));
})();
If you have ArrayBuffer
, you can construct a WebAssembly.Module
object directly.
(async () => {
const resp = await fetch('program.wasm');
const wasm = await resp.arrayBuffer();
// block the main thread until it completes
const module = new WebAssembly.Module(wasm);
// block the main thread until it completes
const instance = new WebAssembly.Instance(module);
console.log(instance.exports.add(1, 2));
})();
In short, use asynchronous APIs to avoid blocking the main thread. Don't use synchronous code not required.