这个问题是为 Yew v0.19 编写的
异步外部 JavaScript 函数可以通过以下方式在 Rust 中使用Closures https://rustwasm.github.io/wasm-bindgen/api/wasm_bindgen/closure/struct.Closure.html#,作为传入的函数:
#[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()
the Model
。但是,那link()
机制在Context
(发出消息)确实not具有静态生命周期。
在理想的情况下,提交给闭包的值可以仅作为 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
}
我想知道是否有办法convert a Callback
into a Closure
,或者如果有更好、更规范的方法来做到这一点,请纠正我。
我的另一个想法是使用某种静态定义的队列(这不安全,因为它是一个可变的静态变量),但它可以用作之间的中间数据类型Closure
传递给createThing
,并且可以在组件内发送消息。
也许有一种与我忽略的 Yew 组件交互的外部方式?我不知道如何解决这个问题。实现这一目标最正确的方法是什么?