mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-06-24 10:11:34 +00:00
Add support for #[wasm_bindgen]
on async fn
(#1754)
This commit adds support to attach `#[wasm_bindgen]` on an `async fn` which will change the return value into a `Promise` in JS. This in theory has the exact same semantics as an `async` function in JS where you call it with all the arguments, nothing happens and you get a promise back, and then later the promise actually resolves. This commit also adds a helper trait, `IntoJsResult`, to allow `async` functions with multiple kinds of return values instead of requiring everything to be `Result<JsValue, JsValue>`.
This commit is contained in:
@ -1,4 +1,76 @@
|
||||
# Converting Between JavaScript `Promise`s and Rust `Future`s
|
||||
# Working with a JS `Promise` and a Rust `Future`
|
||||
|
||||
Many APIs on the web work with a `Promise`, such as an `async` function in JS.
|
||||
Naturally you'll probably want to interoperate with them from Rust! To do that
|
||||
you can use the `wasm-bindgen-futures` crate as well as Rust `async`
|
||||
functions.
|
||||
|
||||
The first thing you might encounter is the need for working with a `Promise`.
|
||||
For this you'll want to use [`js_sys::Promise`]. Once you've got one of those
|
||||
values you can convert that value to `wasm_bindgen_futures::JsFuture`. This type
|
||||
implements the `std::future::Future` trait which allows naturally using it in an
|
||||
`async` function. For example:
|
||||
|
||||
[`js_sys::Promise`]: https://docs.rs/js-sys/*/js_sys/struct.Promise.html
|
||||
|
||||
```rust
|
||||
async fn get_from_js() -> Result<JsValue, JsValue> {
|
||||
let promise = js_sys::Promise::resolved(&42.into());
|
||||
let result = wasm_bindgen_futures::JsFuture::from(promise).await?;
|
||||
Ok(result)
|
||||
}
|
||||
```
|
||||
|
||||
Here we can see how converting a `Promise` to Rust creates a `impl Future<Output
|
||||
= Result<JsValue, JsValue>>`. This corresponds to `then` and `catch` in JS where
|
||||
a successful promise becomes `Ok` and an erroneous promise becomes `Err`.
|
||||
|
||||
Next up you'll probably want to export a Rust function to JS that returns a
|
||||
promise. To do this you can use an `async` function and `#[wasm_bindgen]`:
|
||||
|
||||
```rust
|
||||
#[wasm_bindgen]
|
||||
pub async fn foo() {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
When invoked from JS the `foo` function here will return a `Promise`, so you can
|
||||
import this as:
|
||||
|
||||
```js
|
||||
import { foo } from "my-module";
|
||||
|
||||
async function shim() {
|
||||
const result = await foo();
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
## Return values of `async fn`
|
||||
|
||||
When using an `async fn` in Rust and exporting it to JS there's some
|
||||
restrictions on the return type. The return value of an exported Rust function
|
||||
will eventually become `Result<JsValue, JsValue>` where `Ok` turns into a
|
||||
successfully resolved promise and `Err` is equivalent to throwing an exception.
|
||||
|
||||
The following types are supported as return types from an `async fn`:
|
||||
|
||||
* `()` - turns into a successful `undefined` in JS
|
||||
* `T: Into<JsValue>` - turns into a successful JS value
|
||||
* `Result<(), E: Into<JsValue>>` - if `Ok(())` turns into a successful
|
||||
`undefined` and otherwise turns into a failed promise with `E` converted to a
|
||||
JS value
|
||||
* `Result<T: Into<JsValue>, E: Into<JsValue>>` - like the previous case except
|
||||
both data payloads are converted into a `JsValue`.
|
||||
|
||||
Note that many types implement being converted into a `JsValue`, such as all
|
||||
imported types via `#[wasm_bindgen]` (aka those in `js-sys` or `web-sys`),
|
||||
primitives like `u32`, and all exported `#[wasm_bindgen]` types. In general,
|
||||
you should be able to write code without having too many explicit conversions,
|
||||
and the macro should take care of the rest!
|
||||
|
||||
## Using `wasm-bindgen-futures`
|
||||
|
||||
The `wasm-bindgen-futures` crate bridges the gap between JavaScript `Promise`s
|
||||
and Rust `Future`s. Its `JsFuture` type provides conversion from a JavaScript
|
||||
|
Reference in New Issue
Block a user