You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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会终止,已经注册的全局函数也会失效;如果没等注册逻辑完成就尝试取函数,也会出现取值失败的问题。

修复方案

  1. 调整TS侧取值逻辑,放弃从result.instance.exports取业务函数,改为从全局window对象获取
  2. 等待go.run()执行完成、全局函数注册完毕后再执行业务调用
  3. 补充全局TS类型声明,解决TS静态检查找不到函数定义的报错
  4. 检查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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 05:21:22