Vue项目调用Go编译WASM的StartQuorum函数报错如何解决
Vue集成Go编译WASM时提示StartQuorum不是函数的解决方法
问题根因
该报错和TypeScript类型识别没有直接关系,是两个基础逻辑错误导致的:
- 函数挂载位置错误:Go编写WASM时,
js.Global().Set("StartQuorum", xxx)的逻辑是把业务函数注册到JS全局作用域(window/globalThis),不会出现在result.instance.exports导出表中。Go编译的WASM实例导出项只有Runtime运行需要的内存、基础启动方法,手动注册的业务函数不会进入exports列表,从exports里取自然拿不到目标函数。 - 时序与运行时问题:
go.run()会触发WASM执行main函数完成全局注册,如果main函数执行完直接退出,Go runtime会终止,已经注册的全局函数也会失效;如果没等注册逻辑完成就尝试取函数,也会出现取值失败的问题。
修复方案
- 调整TS侧取值逻辑,放弃从
result.instance.exports取业务函数,改为从全局window对象获取 - 等待
go.run()执行完成、全局函数注册完毕后再执行业务调用 - 补充全局TS类型声明,解决TS静态检查找不到函数定义的报错
- 检查Go侧main函数逻辑,增加阻塞逻辑避免main函数执行完直接退出导致runtime终止
修正后的TS调用代码
import { Go } from './wasm_exec' import quorumWasmUrl from './lib.wasm' // 补充全局类型声明,解决TS类型检查报错 declare global { interface Window { StartQuorum: (password: string, bootstrapStr: string) => Promise<Record<string, any>> } } export const startQuorum = async (bootstraps: Array<string>) => { const go = new Go() const wasmResult = await WebAssembly.instantiateStreaming( fetch(quorumWasmUrl), go.importObject ) // 等待WASM runtime启动、全局函数注册完成 await go.run(wasmResult.instance) const StartQuorum = window.StartQuorum if (typeof StartQuorum !== 'function') { throw new Error('WASM初始化失败,StartQuorum函数未注册') } const res = await StartQuorum('password', bootstraps.join(',')) console.log('startQuorum执行完成', res) return res }
Go侧必要调整
确保main函数在注册完全局函数后不会直接退出,否则Go runtime终止后注册的JS函数会失效,在main函数末尾加阻塞逻辑即可:
func main() { // 原有全局函数注册逻辑 js.Global().Set("StartQuorum", js.FuncOf(func(this js.Value, args []js.Value) interface{} { if qChan == nil { qChan = make(chan struct{}, 0) } if len(args) < 2 { return nil } password := args[0].String() bootAddrsStr := args[1].String() bootAddrs := strings.Split(bootAddrsStr, ",") handler := func() (map[string]interface{}, error) { ret := make(map[string]interface{}) ok, err := StartQuorum(qChan, password, bootAddrs) ret["ok"] = ok if err != nil { return ret, err } return ret, nil } return Promisefy(handler) })) // 阻塞主协程,避免main函数退出 select {} }
内容的提问来源于stack exchange,提问作者LIXIN
相关产品推荐
相关产品推荐

