This code shows the basic steps required to work with a WebSocket.
At first it opens the connection, then subscribes to events onmessage, onerror, onopen.
After the socket is opened it sends a ping message, receives an echoed response
and prints it to the browser console.
#![allow(unused)]fnmain() {
use wasm_bindgen::prelude::*;
use web_sys::{ErrorEvent, MessageEvent, WebSocket};
macro_rules! console_log {
($($t:tt)*) => (log(&format_args!($($t)*).to_string()))
}
#[wasm_bindgen]extern"C" {
#[wasm_bindgen(js_namespace = console)]fnlog(s: &str);
}
#[wasm_bindgen(start)]fnstart_websocket() -> Result<(), JsValue> {
// Connect to an echo serverlet ws = WebSocket::new("wss://echo.websocket.events")?;
// For small binary messages, like CBOR, Arraybuffer is more efficient than Blob handling
ws.set_binary_type(web_sys::BinaryType::Arraybuffer);
// create callbacklet cloned_ws = ws.clone();
let onmessage_callback = Closure::<dynFnMut(_)>::new(move |e: MessageEvent| {
// Handle difference Text/Binary,...ifletOk(abuf) = e.data().dyn_into::<js_sys::ArrayBuffer>() {
console_log!("message event, received arraybuffer: {:?}", abuf);
let array = js_sys::Uint8Array::new(&abuf);
let len = array.byte_length() asusize;
console_log!("Arraybuffer received {}bytes: {:?}", len, array.to_vec());
// here you can for example use Serde Deserialize decode the message// for demo purposes we switch back to Blob-type and send off another binary message
cloned_ws.set_binary_type(web_sys::BinaryType::Blob);
match cloned_ws.send_with_u8_array(&[5, 6, 7, 8]) {
Ok(_) => console_log!("binary message successfully sent"),
Err(err) => console_log!("error sending message: {:?}", err),
}
} elseifletOk(blob) = e.data().dyn_into::<web_sys::Blob>() {
console_log!("message event, received blob: {:?}", blob);
// better alternative to juggling with FileReader is to use https://crates.io/crates/gloo-filelet fr = web_sys::FileReader::new().unwrap();
let fr_c = fr.clone();
// create onLoadEnd callbacklet onloadend_cb = Closure::<dynFnMut(_)>::new(move |_e: web_sys::ProgressEvent| {
let array = js_sys::Uint8Array::new(&fr_c.result().unwrap());
let len = array.byte_length() asusize;
console_log!("Blob received {}bytes: {:?}", len, array.to_vec());
// here you can for example use the received image/png data
});
fr.set_onloadend(Some(onloadend_cb.as_ref().unchecked_ref()));
fr.read_as_array_buffer(&blob).expect("blob not readable");
onloadend_cb.forget();
} elseifletOk(txt) = e.data().dyn_into::<js_sys::JsString>() {
console_log!("message event, received Text: {:?}", txt);
} else {
console_log!("message event, received Unknown: {:?}", e.data());
}
});
// set message event handler on WebSocket
ws.set_onmessage(Some(onmessage_callback.as_ref().unchecked_ref()));
// forget the callback to keep it alive
onmessage_callback.forget();
let onerror_callback = Closure::<dynFnMut(_)>::new(move |e: ErrorEvent| {
console_log!("error event: {:?}", e);
});
ws.set_onerror(Some(onerror_callback.as_ref().unchecked_ref()));
onerror_callback.forget();
let cloned_ws = ws.clone();
let onopen_callback = Closure::<dynFnMut()>::new(move || {
console_log!("socket opened");
match cloned_ws.send_with_str("ping") {
Ok(_) => console_log!("message successfully sent"),
Err(err) => console_log!("error sending message: {:?}", err),
}
// send off binary messagematch cloned_ws.send_with_u8_array(&[0, 1, 2, 3]) {
Ok(_) => console_log!("binary message successfully sent"),
Err(err) => console_log!("error sending message: {:?}", err),
}
});
ws.set_onopen(Some(onopen_callback.as_ref().unchecked_ref()));
onopen_callback.forget();
Ok(())
}
}