使用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
相关产品推荐
相关产品推荐

