为什么我在锈封闭过程中出现终身错误

问题描述

我正在测试一些防锈wasm功能,并且在关闭方面有一些问题。 我实现了此功能,该功能可以在按钮单击事件上设置回调。

<Meta name="_token" content="{{ csrf_token() }}"/>

ws.send rpc的第三个参数是

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);
}

和add_event_listener有这个征兆

pub type RPCHandler = Box<dyn Fn(String) + 'static>;

当我尝试编译代码时,出现生命周期错误

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);
        }
    }
}

解决方法

此代码中不能保证 传递给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
                ...

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...