用 Rust 处理 WebAssembly 中的闭包而不是使用忘记和泄漏内存的更好方法是什么?

8 closures rust webassembly wasm-bindgen

当使用Closures为 JavaScript 提供回调时,有什么更好的方法来避免释放它们?所述WASM-定义BindGen引导建议使用.forget,但承认其基本上泄漏内存。

通常我们会存储句柄以便稍后在适当的时候被删除,但现在我们希望它是一个全局处理程序,所以我们使用该forget方法来删除它而不会使闭包无效。请注意,这是 Rust 中的内存泄漏,因此应该谨慎地进行!

它暗示将闭包存储到适合丢弃的时间。在alexcrichton对上一个问题的回答中,他提到...

[...] 如果它 [...] 只被调用一次,那么你可以使用Rc/RefCell来删除Closure闭包本身的内部(使用一些内部可变性恶作剧)

但他没有提供这种方法的例子。

封闭的文档也给出了参考关闭返回JavaScript的背景下,以让它处理时释放参考的例子。

如果我们cb放在这里,它会在时间间隔过去时引发异常。相反,我们句柄返回给 JS,以便 JS 可以决定何时取消间隔并释放闭包。

我还想象有一些方法可以#[wasm_bindgen]在公共函数上使用生命周期或宏等功能来避免这个问题,但我无法弄清楚如何做到这一点。

我的问题是,使用.forget从 Rust 传递回 JavaScript 的闭包有哪些替代方法,我能否请您查看每个正在使用的选项的简单示例?

Cam*_*art 0

我最近构建了一个小型商业应用程序,并在这个应用程序上停留了数周,当我让它工作时我真的很兴奋。我最终使用了Closure.once_into_js。然而,这也有一个警告:“释放 FnOnce 的唯一方法是调用 JavaScript 函数。如果 JavaScript 函数从未被调用,那么 FnOnce 及其关闭的所有内容都会泄漏。” 因此,如果回调被调用,一切都应该没问题,但如果没有,仍然存在内存泄漏。我发现编程风格非常好。我将 JavaScript 函数映射到 Rust,如下所示:

#[wasm_bindgen]
fn getSomething(details: &JsValue, callback: JsValue);

pub fn get_something(details: &Details, callback: impl Fn(Option<String>) + 'static){
    getSomething(&serde_wasm_bindgen::to_value(details).unwrap(), Closure::once_into_js(move |v: JsValue| 
        callback(serde_wasm_bindgen::from_value(v).unwrap())   
    ));
}
Run Code Online (Sandbox Code Playgroud)

然后我就可以在我的应用程序中从 Rust 使用它,如下所示:

let callback = move |id| {
};
get_something(&details, callback);
Run Code Online (Sandbox Code Playgroud)

我将回调定义为静态 impl 函数,然后将值移入。