【问题标题】:Why does i got lifetime error in rust closure为什么我在防锈闭合时出现终身错误
【发布时间】:2021-01-13 20:33:06
【问题描述】:

我正在测试一些 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)

【问题讨论】:

    标签: rust rust-wasm


    【解决方案1】:

    无法保证在此代码中传递给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
                    ...
    

    【讨论】:

      猜你喜欢
      • 2018-01-20
      • 2022-01-23
      • 2013-05-05
      • 2019-11-04
      • 1970-01-01
      • 1970-01-01
      • 2021-01-11
      • 2016-11-02
      • 2020-04-23
      相关资源
      最近更新 更多