expected `()`, found opaque type for async function

Solution 1:

You declare that your function will not return anything by saying

Box<dyn FnMut(MessageEvent)>
//which is the same thing as Box<dyn FnMut(MessageEvent)->()>

then in your callback, you actually return an async block back.

I am not familiar with the library in question but looking at the documentation you are not supposed to pass an async function.

if you must use async and if you have a runtime running already you can spawn a task inside a sync block.

But in javascript world you cant really wait for something if something is async you can only give it a callback (async/await keywords exists but all they do is to return you another promise)

So I believe you should be using the promise API here and provide a callback for the then method.

It is not pretty but this is how things get done in the js world and what you are facing here is called the callback hell in js which is a thing :D

Ps: Javascript has a single threaded runtime and things get scheduled on a forever running loop called the event loop. Every time you pass a callback somewhere at some point it gets registered on the event loop and gets called eventually.

What's important to understand is that the calling part of it is not guaranteed and if you were to block event loop in one of your callbacks then next tick of the loop would never come therefore the entire runtime would lock up. this is the reason behind the design decisions that lead to the callback hell

Pps:

I don't really think you should bundle (if even its possible) a rust async runtime with your wasm binary since js has its own as I mentioned just stick with the promise api

Solution 2:

The reason is as specified by @nikoss, you pass a future-returning function and cast it to a unit-returning function.

As for how to solve that, you can spawn the future on JS promise microtasks queue with spawn_local():

let (pc1_clone, dc1_clone) = (pc1.clone(), dc1.clone());
let onmessage_callback =
    Closure::wrap(
        Box::new(move |ev: MessageEvent| {
            wasm_bindgen_futures::spawn_local(async move {
                let desc = JsFuture::from(pc1_clone.create_offer()).await.unwrap();
                match ev.data().as_string() {
                    Some(message) => {
                        console_warn!("{:?}", message);
                        dc1_clone.send_with_str("Pong from pc1.dc!").unwrap();
                    }
                    None => {}
                }
            });
        }) as Box<dyn FnMut(MessageEvent)>,
    );
dc1.set_onmessage(Some(onmessage_callback.as_ref().unchecked_ref()));
onmessage_callback.forget();