如何将Go编译的WASM函数导入JS并调用?调用时遇未定义错误
问题:Go编译的WASM函数在JS中调用提示未定义,但控制台可手动调用
问题描述
将Go编译的WASM文件中的函数导入JavaScript使用时,调用函数会出现未定义错误,但WASM导入完成后,在浏览器控制台中可以手动调用该函数,需要实现JS程序内正常调用。
错误信息
Uncaught ReferenceError: add is not defined
现有代码
JavaScript代码
async function init() { const go = new Go(); const result = await WebAssembly.instantiateStreaming( fetch("main.wasm"), go.importObject ); go.run(result.instance); } add("Hello") init();
Go代码
package main import ( "fmt" "syscall/js" ) func add(this js.Value, inputs []js.Value) interface{} { var input string = inputs[0].String() return "you typed: " + input } func main() { fmt.Println("hi") js.Global().Set("add", js.FuncOf(add)) <-make(chan bool) }
解决方案
问题核心是调用时机错误:add("Hello")是同步执行的,而init()是异步函数,此时WASM还未加载完成,add函数还没被注册到全局对象上,因此抛出未定义错误。
只需调整调用时机,确保在WASM初始化完成后再调用add函数,有两种常见修改方式:
方式一:在init函数内部调用
async function init() { const go = new Go(); const result = await WebAssembly.instantiateStreaming( fetch("main.wasm"), go.importObject ); go.run(result.instance); // WASM初始化完成后再调用add add("Hello"); } init();
方式二:用立即执行异步函数等待初始化完成
async function init() { const go = new Go(); const result = await WebAssembly.instantiateStreaming( fetch("main.wasm"), go.importObject ); go.run(result.instance); } // 等待init执行完毕后调用add (async () => { await init(); add("Hello"); })();
原理说明
WebAssembly.instantiateStreaming和go.run都是异步/耗时操作,只有当这些操作完成后,Go代码中的js.Global().Set("add", js.FuncOf(add))才会把add函数挂载到全局对象上。提前调用会因函数尚未存在而报错;而控制台手动调用时,WASM已经加载完成,所以能正常执行。
内容的提问来源于stack exchange,提问作者Crowbin
相关产品推荐
相关产品推荐

