Does Tokio work in the browser if I use only a single thread?

I'm structuring an API to be used within a generic graphical framework. I've just put Tokio inside and wondered how is the support for things like timeout. I'm not planning on exposing thread-based APIs and, once I work on graphics and UI API, I'll structure things that use things like Arc.

Will it just work if I don't use anything from Tokio that involves spawning a thread?

It's only in the gaming API that I'm planning to create threads occasionaly for the Entity-Component-System, trying to get some inspiration from Bevy. However, only for the web browser (in #[cfg(feature = "rialight_browser_export")]), I'd always use a single thread for running a simulation's systems.


Right now I was going to work on the temporal API (which will wrap chrono and chrono-tz probably), but reminded of missing asynchronous timeouts that developers commonly use, so I'm using Tokio internally for asynchronous wait, timeout, interval etc.


At least the basic Tokio runtime works in the browser, even if I don't use any of its functions, right?

1 Like

Once I get things going, if I experience any panic due to thread spawn, I think I'll have to consider using https://crates.io/crates/wasm-bindgen-futures where needed to use setTimeout from JavaScript and create a promise around it (inside my API)

Is there any simple "single-threaded" alternative to Tokio that will allow me to have this?

async fn main() {
}

That is, so that in the browser, I don't need Tokio, and use the web API instead to use timeouts

(I'll use my own attribute macro too to wrap this function: so it wraps with some internal static mutations and an additional asynchronous runtime surrounding the function by either tokio::main or a single-thread something)

The asynchronous runtime would do nothing in this case. It looks like it's not easy to poll

You might want to look through this list - #async // Lib.rs; from the top of my head, Pollster — async Rust library // Lib.rs might be the thing you're looking for. Alternatively, you could pull in futures (which you probably would need in some way anyway) and use block_on in futures::executor - Rust.

1 Like

Existing single-threaded executers tend to sleep the thread while idle; something you can't do in the main browser thread. You'll need to find or develop an executer which ties itself into the browser's event loop instead.

1 Like

This is possible simply using wasm_bindgen_futures. You can write

#[wasm_bindgen]
fn my_entry_point() {
    wasm_bindgen_futures::spawn_local(async move {
        // async code goes here
    });
}

or if you want the JS side to get a Promise, use wasm_bindgen_futures::future_to_promise() instead. Since you plan to write an attribute macro — write it to produce this code. That's essentially what tokio::main does for other platforms

Yes. That's exactly what wasm_bindgen_futures is.

3 Likes