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

Yew v0.19中如何将Callback用作wasm_bindgen Closure

本问题针对Yew v0.19版本编写

核心问题场景

Rust中可通过Closure传入函数,实现异步外部JavaScript函数的调用,基础用法示例如下:

#[wasm_bindgen]
extern "C" {
    fn setInterval(closure: &Closure<dyn FnMut()>, time: u32) -> i32;
}

// ...

let cb = Closure::new(|| {
    log("interval elapsed!");
});

let interval_id = setInterval(&cb, 1_000);

上述示例逻辑清晰,但Closure存在一项核心约束:传入的函数必须满足'static生命周期要求。在Yew应用中,实现自发事件响应的标准机制是Message枚举,通过update()方法更新Model状态;但Context中负责发送消息的link()机制并不具备静态生命周期。

理想场景下,闭包接收到的返回值可直接作为Yew组件消息提交,对应实现代码如下:

struct Model {
    thing: Option<JsValue>,
}

enum Msg {
    GotThing(JsValue),
}

#[wasm_bindgen]
extern "C" {
    fn createThing(closure: &Closure<dyn FnMut(JsValue) -> ()>);
}

impl Component for Model {
    type Message = Msg;
    type Properties = ();

    fn create(_ctx: &Context<Self>) -> Self {
        Model {
            thing: None, // initial value
        }
    }

    fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
        match msg {
            Msg::GotThing(x) => { // handle the message
                self.thing = Some(x);
                true
            },
        }
    }

    fn rendered(&mut self, ctx: &Context<Self>, first_render: bool) {
        if first_render {
            let cb: Box<dyn FnMut(JsValue) -> ()> = Box::new(|x| {
                // try and issue the message
                ctx.link().send_message(Msg::GotThing(x));
                // ^ doesn't have a `'static` lifetime! Won't compile
            });
            createThing(Closure::wrap(&cb));
        }
    }

    // fn view() ... omitted, not relevant
}
待确认诉求
  • 是否存在将Callback转换为Closure的可行方案,或是更符合Yew设计规范的标准实现方式
  • 曾考虑通过静态定义的队列作为传入createThing的Closure与组件内部消息派发之间的中介结构,实现组件内的消息正常派发,但可变静态变量存在安全风险,想确认是否存在尚未注意到的Yew组件外部交互方式
  • 明确解决该问题的最规范实现方案

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 10:18:22