(This issue is mostly opened for "discussion" purposes, trying to reach the right target audience)
A lot of people will probably have the use-case of mapping a Rust futures::Future to an ES6 Promise. My solution right now has been to do this:
fn foo() -> impl futures::Future<Item = String, Error = String> {
// ...
}
#[wasm_bindgen]
struct JsApi { /* ... */ }
#[wasm_bindgen]
impl JsApi {
pub fn foo(&self, resolve: JsValue, reject: JsValue) {
let future = foo()
.map(move |s| resolveString(resolve, s))
.map_err(move |e| rejectString(reject, e));
self.executor.spawn(future);
}
}
#[wasm_bindgen(module = "../ffi")]
extern "C" {
#[allow(non_snake_case)]
fn resolveString(resolve: JsValue, string: String);
#[allow(non_snake_case)]
fn rejectString(reject: JsValue, string: String);
}
Then, in ffi.ts:
export function resolveString(resolve: (value: string) => void, value: string) {
console.debug("resolved:", value);
resolve(value);
}
export function rejectString(reject: (value: string) => void, value: string) {
console.warn("rejected:", value);
reject(value);
}
...and finally:
export function foo() {
return new Promise<string>((resolve, reject) => wasm.foo(resolve, reject));
}
This is quite verbose and lots of boilerplate. Some ideas on what might help:
JsValues from Rust.Promise/Future in particular since it might be a common use-case.Any other ideas on how to improve this?
I think this'd be a fantastic idea! I unfortunately haven't figure out much of a way to work with closures and wasm-bindgen today, but I'm hopeful that we can figure that out soon to start binding APIs like promises!
I have integrated ES Promises and Futures (and tokio) once before, and I wrote a bit about the gotchas that will be encountered: https://github.com/starlingjs/starling/blob/master/src/promise_future_glue.rs#L1-L67
In addition to @fitzgen's link I think we'll want to tackle https://github.com/alexcrichton/wasm-bindgen/issues/78 before trying to make too much progress here as well
I have added in an excellent (and very fast) Executor to stdweb.
And it's easy to convert from Future -> Promise or from Promise -> Future.
This might help out with Future / Promise support in wasm-bindgen. Feel free to ask me for advice.
Nice! I think that's some great work to start from. I think an integration crate like this would probably start out as a separate crate rather than built into wasm-bindgen itself, and I'd be totally down for reviewing PRs to do so.
I used a similar approach myself for now: https://github.com/dflemstr/semantic-editor/blob/master/src/executor/sys/wasm/mod.rs
It leverages a copy-pasted version of the current_thread executor from tokio, hooking in the microtask scheduler as a back-end. I think long term it would be great to just use tokio directly and add changes upstream to make it work with wasm, although I'm not sure how it should interact with the required browser microtask API?
Support for this is added in https://github.com/rustwasm/wasm-bindgen/pull/600
Most helpful comment
https://github.com/rustwasm/wasm-bindgen/pull/600 merged!