Cancel Rust function from JavaScript

152 views Asked by At

I have a long running wasm function written in Rust which should be cancelable by the user (for example, by clicking a cancel button in the UI), that is, by a JavaScript event. My idea is to use a custom cancellation token like that:

#[wasm_bindgen]
pub struct JsCancellationToken {
    token: Cell<bool>,
}

#[wasm_bindgen]
impl JsCancellationToken {
    pub fn new() -> JsCancellationToken {
        JsCancellationToken {
            token: Cell::new(false),
        }
    }

    pub fn cancel(&self) {
        self.token.set(true)
    }

    pub async fn is_cancellation_requested(&self) -> bool {
        handle_js_events().await;
        self.token.get()
    }
}

#[wasm_bindgen]
pub async fn long_running_function(ct: &JsCancellationToken) -> u32 {
    while !ct.is_cancellation_requested().await {
        ...
    }
    ...
}

The crucial detail is the (custom) handle_js_events function which prevents long_running_function from blocking the JavaScript event queue forever. My naive implementation of that function looks like that:

use js_sys::{Function, Promise};
use wasm_bindgen_futures::JsFuture;

#[wasm_bindgen]
extern "C" {
    fn setTimeout(closure: &Function, millis: u32);
}

async fn handle_js_events() {
    JsFuture::from(Promise::new(
        &mut |resolve: Function, _reject: Function| {
            setTimeout(&resolve, 0);
        },
    ))
    .await
    .unwrap();
}

This is working, but it always feel hacky to use setTimeout(..., 0). Is there a more direct way to interrupt work for a moment and make JavaScript handle the latest events? Or is there an even better way to cancel a wasm function from the UI?

0

There are 0 answers