如何检测何时准备好使用 asm.js 模块中加载的函数
How to detect when you are ready to use functions loaded in asm.js module
我正在使用 emscripten 生成一个文件 a.wasm.js,其中包含用于加密的 C++ 函数。 Webassembly 函数接受 return 保存 JSON 数据的 C 字符串。我想包装这些 asm.js 函数以便在我的客户端应用程序中更方便地使用。不幸的是,直接在 body.onload 中执行它似乎不起作用,所以我正在使用以下技巧:
<script>
!function(e, t){
console.log("Loading client...");
var n = "a.wasm.js";
if(!e.WebAssembly){
n = "a.js"
}
console.log("Script set to " + n);
var o = t.createElement("script");
o.async = true, o.type = "text/javascript", o.src = n, o.onerror = function(t) {
console.error("Script Error"), console.error(t), setTimeout(function() {
e.location.reload(!0)
}, 3e3)
};
var r = t.getElementsByTagName("script")[0];
r.parentNode.insertBefore(o, r)
}(window, document);
</script>
<script>
setTimeout(function(){
let _generateKeyPair = Module.cwrap('generateKeyPair', 'string', null);
window.generateKeyPair = function() {
return JSON.parse(_generateKeyPair());
}
}, 1000)
</script>
当然,这里的问题是我在应用程序加载后 1 秒后才能使用“generateKeyPair”。
是否有任何回调我可以挂钩以了解 asm.js 模块对象已完全加载并且我可以开始使用其中定义的函数?
一种方法是定义并等待 Module.ready
Promise。这是在 Emscripten 编译期间使用 --post-js
标志注入的。 (see full examples)
<script src="wasm-module.js"></script>
<script>
Module.ready
.then(api => console.log( api.sayHello() ))
.catch(e => console.error('', e))
</script>
$ emcc \
-O0 `# leave uncompressed for example` \
-s WASM=1 \
-s EXPORTED_FUNCTIONS="['_hello']" \
-s EXTRA_EXPORTED_RUNTIME_METHODS="['cwrap']" \
-o wasm-module.js \
--post-js module-post.js \
hello.c
// hello.c
char *hello() {
return "Hello there. Welcome to WebAssembly.";
}
// module-post.js
// Module.ready resolves when WASM instantiates. (ready is now a property and not function via @surma fork)
Module.ready = new Promise(function(resolve, reject) {
addOnPreMain(function() {
var api = {
sayHello: Module.cwrap('hello', 'string', [])
};
resolve(api);
});
// Propagate error to Module.ready.catch()
// WARNING: this is a hack based Emscripten's current abort() implementation
// and could break in the future.
// Rewrite existing abort(what) function to reject Promise before it executes.
var origAbort = this.abort;
this.abort = function(what) {
reject(Error(what));
origAbort.call(this, what);
}
});
我正在使用 emscripten 生成一个文件 a.wasm.js,其中包含用于加密的 C++ 函数。 Webassembly 函数接受 return 保存 JSON 数据的 C 字符串。我想包装这些 asm.js 函数以便在我的客户端应用程序中更方便地使用。不幸的是,直接在 body.onload 中执行它似乎不起作用,所以我正在使用以下技巧:
<script>
!function(e, t){
console.log("Loading client...");
var n = "a.wasm.js";
if(!e.WebAssembly){
n = "a.js"
}
console.log("Script set to " + n);
var o = t.createElement("script");
o.async = true, o.type = "text/javascript", o.src = n, o.onerror = function(t) {
console.error("Script Error"), console.error(t), setTimeout(function() {
e.location.reload(!0)
}, 3e3)
};
var r = t.getElementsByTagName("script")[0];
r.parentNode.insertBefore(o, r)
}(window, document);
</script>
<script>
setTimeout(function(){
let _generateKeyPair = Module.cwrap('generateKeyPair', 'string', null);
window.generateKeyPair = function() {
return JSON.parse(_generateKeyPair());
}
}, 1000)
</script>
当然,这里的问题是我在应用程序加载后 1 秒后才能使用“generateKeyPair”。
是否有任何回调我可以挂钩以了解 asm.js 模块对象已完全加载并且我可以开始使用其中定义的函数?
一种方法是定义并等待 Module.ready
Promise。这是在 Emscripten 编译期间使用 --post-js
标志注入的。 (see full examples)
<script src="wasm-module.js"></script>
<script>
Module.ready
.then(api => console.log( api.sayHello() ))
.catch(e => console.error('', e))
</script>
$ emcc \
-O0 `# leave uncompressed for example` \
-s WASM=1 \
-s EXPORTED_FUNCTIONS="['_hello']" \
-s EXTRA_EXPORTED_RUNTIME_METHODS="['cwrap']" \
-o wasm-module.js \
--post-js module-post.js \
hello.c
// hello.c
char *hello() {
return "Hello there. Welcome to WebAssembly.";
}
// module-post.js
// Module.ready resolves when WASM instantiates. (ready is now a property and not function via @surma fork)
Module.ready = new Promise(function(resolve, reject) {
addOnPreMain(function() {
var api = {
sayHello: Module.cwrap('hello', 'string', [])
};
resolve(api);
});
// Propagate error to Module.ready.catch()
// WARNING: this is a hack based Emscripten's current abort() implementation
// and could break in the future.
// Rewrite existing abort(what) function to reject Promise before it executes.
var origAbort = this.abort;
this.abort = function(what) {
reject(Error(what));
origAbort.call(this, what);
}
});