为什么我在生锈关闭时出现终身错误
Why does i got lifetime error in rust closure
我正在测试一些 Rust wasm 功能,但遇到一些闭包问题。
我实现了这个功能,它设置了按钮点击事件的回调。
pub fn setup_click(&mut self) {
let mut clicks = 0;
let ws_cloned = self.websocket.clone();
let num_clicks_cloned = self.num_clicks.clone();
let notifications = Rc::new(RefCell::new(Notificator::new(
NotificationConfig::new_default(),
)));
let cb = move |_: Event| {
clicks += 1;
num_clicks_cloned
.borrow_mut()
.set_inner_html(clicks.to_string());
let mut map: Map<String, Value> = serde_json::Map::new();
map.insert("key".to_string(), Value::String(clicks.to_string()));
if let Ok(ws) = ws_cloned.clone().try_borrow_mut() {
ws.send_rpc(
String::from("click"),
Params::Map(map),
Box::new(|payload: String| {
notifications.clone().borrow_mut().display(
payload,
"Click success".to_string(),
"success".to_string(),
)
}),
);
}
};
self.click_button.add_event_listener("click", cb);
}
ws.send rpc 的第三个参数是
pub type RPCHandler = Box<dyn Fn(String) + 'static>;
和add_event_listener有这个签名
pub fn add_event_listener<T>(&mut self, event_name: &str, handler: T)
where
T: 'static + FnMut(web_sys::Event),
{
let cb = Closure::wrap(Box::new(handler) as Box<dyn FnMut(_)>);
if let Some(el) = self.el.take() {
let el_et: EventTarget = el.into();
el_et
.add_event_listener_with_callback(event_name, cb.as_ref().unchecked_ref())
.unwrap();
cb.forget();
if let Ok(el) = el_et.dyn_into::<web_sys::Element>() {
self.el = Some(el);
}
}
}
当我尝试编译代码时出现生命周期错误
--> src/test_click_btn.rs:46:21
|
35 | let cb = move |_: Event| {
| --------------- lifetime `'1` represents this closure's body
...
46 | / Box::new(|payload: String| {
47 | | notifications.clone().borrow_mut().display(
48 | | payload,
49 | | "Click success".to_string(),
50 | | "success".to_string(),
51 | | )
52 | | }),
| |______________________^ cast requires that `'1` must outlive `'static`
|
= note: closure implements `FnMut`, so references to captured variables can't escape the closure```
I see that notifications not live long enough, but can't understand how to fix this error)
无法保证在此代码中传递给send_rpc
的闭包将持续不超过事件回调闭包。因此,它也需要制作a move
closure,这样它就可以独立存在而不是借用事件处理程序闭包。
方便的是,您已经将 notifications
包裹在 Rc
中,这正是您所需要的,但是您在错误的位置执行了克隆。这一行
notifications.clone().borrow_mut().display(
执行克隆并立即取消引用,因此它是多余的。相反,您需要在创建闭包 之前克隆它 ,以便闭包(现在 move
)可以拥有它:
let notifications = notifications.clone(); // create a clone that will be moved into the closure
ws.send_rpc(
String::from("click"),
Params::Map(map),
Box::new(move |payload: String| { // now a move closure
notifications.borrow_mut().display( // no clone here
...
我正在测试一些 Rust wasm 功能,但遇到一些闭包问题。 我实现了这个功能,它设置了按钮点击事件的回调。
pub fn setup_click(&mut self) {
let mut clicks = 0;
let ws_cloned = self.websocket.clone();
let num_clicks_cloned = self.num_clicks.clone();
let notifications = Rc::new(RefCell::new(Notificator::new(
NotificationConfig::new_default(),
)));
let cb = move |_: Event| {
clicks += 1;
num_clicks_cloned
.borrow_mut()
.set_inner_html(clicks.to_string());
let mut map: Map<String, Value> = serde_json::Map::new();
map.insert("key".to_string(), Value::String(clicks.to_string()));
if let Ok(ws) = ws_cloned.clone().try_borrow_mut() {
ws.send_rpc(
String::from("click"),
Params::Map(map),
Box::new(|payload: String| {
notifications.clone().borrow_mut().display(
payload,
"Click success".to_string(),
"success".to_string(),
)
}),
);
}
};
self.click_button.add_event_listener("click", cb);
}
ws.send rpc 的第三个参数是
pub type RPCHandler = Box<dyn Fn(String) + 'static>;
和add_event_listener有这个签名
pub fn add_event_listener<T>(&mut self, event_name: &str, handler: T)
where
T: 'static + FnMut(web_sys::Event),
{
let cb = Closure::wrap(Box::new(handler) as Box<dyn FnMut(_)>);
if let Some(el) = self.el.take() {
let el_et: EventTarget = el.into();
el_et
.add_event_listener_with_callback(event_name, cb.as_ref().unchecked_ref())
.unwrap();
cb.forget();
if let Ok(el) = el_et.dyn_into::<web_sys::Element>() {
self.el = Some(el);
}
}
}
当我尝试编译代码时出现生命周期错误
--> src/test_click_btn.rs:46:21
|
35 | let cb = move |_: Event| {
| --------------- lifetime `'1` represents this closure's body
...
46 | / Box::new(|payload: String| {
47 | | notifications.clone().borrow_mut().display(
48 | | payload,
49 | | "Click success".to_string(),
50 | | "success".to_string(),
51 | | )
52 | | }),
| |______________________^ cast requires that `'1` must outlive `'static`
|
= note: closure implements `FnMut`, so references to captured variables can't escape the closure```
I see that notifications not live long enough, but can't understand how to fix this error)
无法保证在此代码中传递给send_rpc
的闭包将持续不超过事件回调闭包。因此,它也需要制作a move
closure,这样它就可以独立存在而不是借用事件处理程序闭包。
方便的是,您已经将 notifications
包裹在 Rc
中,这正是您所需要的,但是您在错误的位置执行了克隆。这一行
notifications.clone().borrow_mut().display(
执行克隆并立即取消引用,因此它是多余的。相反,您需要在创建闭包 之前克隆它 ,以便闭包(现在 move
)可以拥有它:
let notifications = notifications.clone(); // create a clone that will be moved into the closure
ws.send_rpc(
String::from("click"),
Params::Map(map),
Box::new(move |payload: String| { // now a move closure
notifications.borrow_mut().display( // no clone here
...