Search code examples
asynchronousrustwebassembly

Rust wasm: How to wait for Future to resolve


I have the following WASM code with the asynchronous function request_data that performs an asynchronous call to an arbitrary API and logs the resolved Promise to the console. To check for orchestration, I am logging before and after I execute this function. Naturally, when I am not specifying to wait for the asynchronous function, its output will be logged after my surrounding logs:

use wasm_bindgen::prelude::*;

#[wasm_bindgen(inline_js = "export async function request_data() { console.log(await <some_async_call>) }")]
extern {
    pub async fn request_data();
}

#[wasm_bindgen(inline_js = "export function log(text) { console.log(text) }")]
extern {
    pub fn log(text: &str);
}

#[wasm_bindgen]
pub fn main() {
    log("Before");
    request_data();
    log("After");
}

When I run function main, I am getting the following output to the console:

Before
After
<async call result data>

What I want to achieve is to let the main function wait until the Future resolves, before it is logging "After". I tried the following, but it just endlessly wait for the Future to resolve:

use wasm_bindgen::prelude::*;
use futures::executor::*;

#[wasm_bindgen(inline_js = "export async function request_data() { console.log(await <some_async_call>) }")]
extern {
    pub async fn request_data();
}

#[wasm_bindgen(inline_js = "export function log(text) { console.log(text) }")]
extern {
    pub fn log(text: &str);
}

#[wasm_bindgen]
pub fn main() {
    log("Before");
    block_on(request_data());
    log("After");
}

This just leads to this output

Before

So my question is, how I can orchestrate the main function to get the following output:

Before
<async call result data>
After

Solution

  • Make the calling function async too:

    #[wasm_bindgen]
    pub async fn main() {
        log("Before");
        request_data().await;
        log("After");
    }
    

    When this function is exported to JavaScript, it will become a function returning a Promise, just like a JS async function. That's all you need to do, usually.


    From the perspective of Rust async, the browser provides an already-existing, single-threaded async executor. You should not use any other async executor within it. The wasm-bindgen-futures library provides API for explicitly working with promises and futures if you need to.