How does Rust/wasm32/async interact with JS being single threaded, and event handlers?

Consider: web-sys: using fetch - The `wasm-bindgen` Guide

Now imagine we are fetching a 10MB file over a 56.6 k modem.

At the same time, imagine the user is moving the mouse around and triggering all types of event handlers.

Question:

Mechanically, how does async interact with the JS event handlers and JS being single threaded to make this all work ?

  1. 10MB over a 56.6 k modem is going to take a while

  2. the page needs to be responsive as the user moves the mouse around while the file is being fetched

  3. how exactly, mechanically, is the Rust async function being suspended and resuming to make this all happen ?

[I am familiar with using tokio async; what I am not familiar with is the async runtime on Chrome.]

Thanks!

It works by yielding. Whenever more data arrives, the wasm starts running to process it, then it is suspended and control is given back to the browser until another piece of data arrives. Thus, the browser can process things such as mouse events while the wasm is suspended.

2 Likes

How does async Rust on wasm32 "yield" ? Is it by compiling it to a chain of JS handlers where each JS handler resumes some wasm32 Rust code ?

I haven't looked closely into the details, but I am pretty sure that the WASM modules provide a poll function, and that JS will call the poll function from the appropriate JS event handlers when something happens. It yields by simply returning from this function.

In JS, we can express this pogram:

download url1: and callback foo1

download url2: and callback foo2

and the downloads/GET requests happen in concurrent, and we don't know whether foo1 or foo2 is called first

===

How do we express this program in async rust? does wasm have multiple entry points, one for foo1, one for foo2; or is there only one entry point but it somehow distinguishes if it's going foo1/url1 or foo2/url2 ?

You have in JS Promise
In rust pub async fn generates a function that returns a Future structure with poll()
The #[wasm_bindgen] creates a JS function Promise that is like calling tokio::spawn(run())
It gets called here.

Downloading does not happen in WASM it is done using Fetch

To do concurrent downloads from single function call either;
Set code to be call in then after window.fetch_with_request(&request)
or join or select Futures that come JsFuture::from(window.fetch_with_request(&request))

2 Likes