Hello!
I'm trying to implement a web socket client in wasm. I use this example. I'm adding a channel to use received messages in other application module and have an error when use the Sender
in a Closure
. There is minimal reproduction code:
Cargo.toml
[package]
name = "demo"
version = "0.1.0"
edition = "2021"
[dependencies]
js-sys = "0.3.77"
wasm-bindgen = "0.2.100"
crossbeam = "0.8.4"
[dependencies.web-sys]
version = "0.3.77"
features = [
"BinaryType",
"Blob",
"ErrorEvent",
"FileReader",
"MessageEvent",
"ProgressEvent",
"WebSocket",
]
src/main.rs
use crossbeam::channel::{unbounded, Receiver, Sender};
use wasm_bindgen::prelude::*;
use web_sys::MessageEvent;
macro_rules! console_log {
($($t:tt)*) => (log(&format_args!($($t)*).to_string()))
}
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = console)]
fn log(s: &str);
}
fn main() {
let (sender, _receiver): (
Sender<String>,
Receiver<String>,
) = unbounded();
let _onmessage_callback = Closure::<dyn FnMut(_)>::new(move |e: MessageEvent| {
if let Ok(blob) = e.data().dyn_into::<web_sys::Blob>() {
console_log!("message event, received blob: {:?}", blob);
// [...]
let onloadend_cb = Closure::<dyn FnMut(_)>::new(move |_e: web_sys::ProgressEvent| {
// [...]
sender.send("ReceivedMessage".to_string()).unwrap();
});
// [...]
} else {
console_log!("message event, received Unknown: {:?}", e.data());
}
});
}
This produce the error (when add the line sender.send("ReceivedMessage".to_string()).unwrap();
):
error[E0525]: expected a closure that implements the `FnMut` trait, but this closure only implements `FnOnce`
--> src/main.rs:22:60
|
22 | let _onmessage_callback = Closure::<dyn FnMut(_)>::new(move |e: MessageEvent| {
| ---------------------------- -^^^^^^^^^^^^^^^^^^^^^
| | |
| _______________________________|____________________________this closure implements `FnOnce`, not `FnMut`
| | |
| | required by a bound introduced by this call
23 | | if let Ok(blob) = e.data().dyn_into::<web_sys::Blob>() {
24 | | console_log!("message event, received blob: {:?}", blob);
25 | | // [...]
... |
28 | | sender.send("ReceivedMessage".to_string()).unwrap();
| | ------ closure is `FnOnce` because it moves the variable `sender` out of its environment
... |
33 | | }
34 | | });
| |_____- the requirement to implement `FnMut` derives from here
|
= note: required for `{closure@src/main.rs:22:60: 22:82}` to implement `IntoWasmClosure<dyn FnMut(MessageEvent)>`
note: required by a bound in `wasm_bindgen::prelude::Closure::<T>::new`
--> /home/bastiensevajol/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wasm-bindgen-0.2.100/src/closure.rs:274:12
|
272 | pub fn new<F>(t: F) -> Closure<T>
| --- required by a bound in this associated function
273 | where
274 | F: IntoWasmClosure<T> + 'static,
| ^^^^^^^^^^^^^^^^^^ required by this bound in `Closure::<T>::new`
I'm not familiar with FnOnce
and FnMut
and I have no idea about what happen. Any idea ? Thanks !