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

使用wasm-pack/Rust生成的JS类实例调用非静态函数报错

问题:Wasm-bindgen异步构造函数实例无法调用非静态方法

我使用wasm-pack 0.13.0、wasm-bindgen与Rust编写了StateW类,该类包含异步构造函数和非静态方法renderWasm。编译生成JS类后,在Chrome 128.0.6613.120(arm64)浏览器中实例化StateW并调用renderWasm方法时,出现错误:Uncaught TypeError: statew.renderWasm is not a function。静态方法可正常调用,尝试修改类名、函数名、变量类型等方式均无法解决。


Rust代码

use wasm_bindgen::prelude::*;
use web_sys::HtmlCanvasElement;
use wgpu::{Surface, SurfaceError};

#[wasm_bindgen]
extern "C" {
    #[wasm_bindgen(js_namespace = console)]
    fn log(s: String);
}

#[wasm_bindgen]
// #[derive(Debug)]
struct StateW {
    state_wasm: StateWasm<'static>,
}

#[derive(Debug)]
struct StateWasm<'a> {
    instance: wgpu::Instance,
    surface: Surface<'a>,
    device: wgpu::Device,
    queue: wgpu::Queue,
    config: wgpu::SurfaceConfiguration,
    size: (u32, u32),
}

impl<'a> StateWasm<'a> {
    pub async fn new(canvas: HtmlCanvasElement) -> Self {..}

    pub fn render(&mut self) -> Result<(), SurfaceError> {..}
}

#[wasm_bindgen]
impl StateW {
    #[wasm_bindgen(constructor)]
    pub async fn new(canvas: HtmlCanvasElement) -> Self {
        Self {
            state_wasm: StateWasm::new(canvas).await,
        }
    }

    #[wasm_bindgen(js_name="renderWasm")]
    pub fn render_wasm(&mut self) {
        let error = self.state_wasm.render();
        match error {
            Ok(_) => {},
            Err(e) => log(e.to_string()),
        };
    }

    pub fn good() -> String {
        String::new()
    }
}

wasm-pack生成的JS类代码

export class StateW {

    static __wrap(ptr) {
        ptr = ptr >>> 0;
        const obj = Object.create(StateW.prototype);
        obj.__wbg_ptr = ptr;
        StateWFinalization.register(obj, obj.__wbg_ptr, obj);
        return obj;
    }

    __destroy_into_raw() {
        const ptr = this.__wbg_ptr;
        this.__wbg_ptr = 0;
        StateWFinalization.unregister(this);
        return ptr;
    }

    free() {
        const ptr = this.__destroy_into_raw();
        wasm.__wbg_statew_free(ptr, 0);
    }
    /**
    * @param {HTMLCanvasElement} canvas
    */
    constructor(canvas) {
        const ret = wasm.statew_new(addHeapObject(canvas));
        return takeObject(ret);
    }
    /**
    */
    renderWasm() {
        wasm.statew_renderWasm(this.__wbg_ptr);
    }
    /**
    * @returns {string}
    */
    static good() {
        let deferred1_0;
        let deferred1_1;
        try {
            const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
            wasm.statew_good(retptr);
            var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
            var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
            deferred1_0 = r0;
            deferred1_1 = r1;
            return getStringFromWasm0(r0, r1);
        } finally {
            wasm.__wbindgen_add_to_stack_pointer(16);
            wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
        }
    }
}

JS调用代码

import init, { StateW } from './pkg/game.js';

await init();

document.body.setAttribute("style", "margin:0;")

let canvas = document.getElementById("canvas");
canvas.width = innerWidth;
canvas.height = innerHeight;
 
const statew = new StateW(canvas);

console.log(StateW.good());
statew.renderWasm();

错误信息

Uncaught TypeError: statew.renderWasm is not a function
    at index.js:15:8

解决方案

问题核心是异步构造函数的返回值处理:

Rust中用#[wasm_bindgen(constructor)]标记的异步函数,在JS端会被包装成返回Promise的构造逻辑,而非直接返回实例对象。你当前代码里的const statew = new StateW(canvas)得到的是一个Promise,不是StateW实例,自然找不到renderWasm方法。

只需给实例化代码加上await即可:

// 修改前
const statew = new StateW(canvas);
// 修改后
const statew = await new StateW(canvas);

静态方法不受影响是因为它们不需要依赖实例,直接挂载在类上,所以调用正常。

内容的提问来源于stack exchange,提问作者Arif

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 14:50:53