1
0
mirror of https://github.com/google/comprehensive-rust.git synced 2025-05-23 10:50:18 +02:00
This commit is contained in:
sakex 2023-07-24 22:10:51 +02:00
parent 13af2243ec
commit f7d791fac7
3 changed files with 80 additions and 0 deletions

View File

@ -306,6 +306,8 @@
- [Expose user-defined Rust types](webassembly/expose-rust-type.md)
- [Import user-defined Javascript types](webassembly/import-js-type.md)
- [Borrow Checker](webassembly/borrow-checker.md)
- [Async](webassembly/async.md)
# Final Words

View File

@ -75,6 +75,9 @@
border-radius: 5px;
font-weight: bold;
cursor: pointer;
display: inline-block;
min-height: 1em;
min-width: 1em;
}
img {

75
src/webassembly/async.md Normal file
View File

@ -0,0 +1,75 @@
# Async
Rust methods in WebAssembly can be declared async. Once called, they will be scheduled on the browser's event loop.
An event handler can for instance be implemented with a tokio channel.
Instead of `tokio::spawn`, `wasm_bindgen` provides `wasm_bindgen_futures::spawn_local`.
Let's create a class that waits for messages on a channel to rotate an HTML element:
```rust
#[derive(Debug)]
enum RotateSide {
Left,
Right,
}
#[wasm_bindgen]
pub struct Rotator {
sender: Sender<RotateSide>,
}
#[wasm_bindgen]
impl Rotator {
#[wasm_bindgen(constructor)]
pub fn new(element: web_sys::HtmlElement) -> Rotator {
let (sender, mut receiver) = channel::<RotateSide>(1);
spawn_local(async move {
let mut rotation = 0;
while let Some(rotate_side) = receiver.recv().await {
log(&format!("Rotation: {}", rotation));
match rotate_side {
RotateSide::Left => rotation -= 45,
RotateSide::Right => rotation += 45,
}
element.set_inner_html(&rotation.to_string());
let style = element.style();
style
.set_property("transform", &format!("rotate({rotation}deg)"))
.expect("Failed to rotate");
}
});
Rotator { sender }
}
#[wasm_bindgen]
pub async fn rotate(&self, msg: String) -> Result<(), JsValue> {
let rotate_side = match msg.as_str() {
"ArrowLeft" => RotateSide::Left,
"ArrowRight" => RotateSide::Right,
_ => return Ok(()),
};
self.sender
.send(rotate_side)
.await
.map_err(|e| JsValue::from_str(&format!("Receiver dropped {:?}", e)))
}
}
```
Let's call it from Javascript
```javascript
import init, {Rotator} from '/wasm/project.js';
(async () => {
// Run the init method to initiate the WebAssembly module.
await init();
const wasmoutput = document.querySelector('#wasmoutput');
const rotator = new Rotator(wasmoutput);
document.body.addEventListener('keydown', async (e) => {
await rotator.rotate(e.key);
});
})();
```