#futures #bindgen #gap #future #bridges #conversions

wasm-bindgen-futures

Bridging the gap between Rust Futures and JavaScript Promises

35 releases

✓ Uses Rust 2018 edition

new 0.3.27 Aug 19, 2019
0.3.25 Jul 11, 2019
0.3.17 Mar 22, 2019
0.3.6 Dec 4, 2018
0.3.5 Nov 12, 2018

#14 in WebAssembly

Download history 2051/week @ 2019-05-06 2211/week @ 2019-05-13 2882/week @ 2019-05-20 2214/week @ 2019-05-27 2442/week @ 2019-06-03 2733/week @ 2019-06-10 3323/week @ 2019-06-17 2610/week @ 2019-06-24 2496/week @ 2019-07-01 3258/week @ 2019-07-08 2922/week @ 2019-07-15 2485/week @ 2019-07-22 2279/week @ 2019-07-29 3077/week @ 2019-08-05 4436/week @ 2019-08-12

12,099 downloads per month
Used in 90 crates (29 directly)

MIT/Apache

463KB
4.5K SLoC

wasm-bindgen-futures

API Documention

This crate bridges the gap between a Rust Future and a JavaScript Promise. It provides two conversions:

  1. From a JavaScript Promise into a Rust Future.
  2. From a Rust Future into a JavaScript Promise.

See the API documentation for more info.


lib.rs:

Converting between JavaScript Promises to Rust Futures.

This crate provides a bridge for working with JavaScript Promise types as a Rust Future, and similarly contains utilities to turn a rust Future into a JavaScript Promise. This can be useful when working with asynchronous or otherwise blocking work in Rust (wasm), and provides the ability to interoperate with JavaScript events and JavaScript I/O primitives.

There are two main interfaces in this crate currently:

  1. JsFuture

    A type that is constructed with a Promise and can then be used as a Future<Item = JsValue, Error = JsValue>. This Rust future will resolve or reject with the value coming out of the Promise.

  2. future_to_promise

    Converts a Rust Future<Item = JsValue, Error = JsValue> into a JavaScript Promise. The future's result will translate to either a rejected or resolved Promise in JavaScript.

These two items should provide enough of a bridge to interoperate the two systems and make sure that Rust/JavaScript can work together with asynchronous and I/O work.

Example Usage

This example wraps JavaScript's Promise.resolve() into a Rust Future for running tasks on the next tick of the micro task queue. The futures built on top of it can be scheduled for execution by conversion into a JavaScript Promise.

extern crate futures;
extern crate js_sys;
extern crate wasm_bindgen;
extern crate wasm_bindgen_futures;

use futures::{Async, Future, Poll};
use wasm_bindgen::prelude::*;
use wasm_bindgen_futures::{JsFuture, future_to_promise};

/// A future that becomes ready after a tick of the micro task queue.
pub struct NextTick {
    inner: JsFuture,
}

impl NextTick {
    /// Construct a new `NextTick` future.
    pub fn new() -> NextTick {
        // Create a resolved promise that will run its callbacks on the next
        // tick of the micro task queue.
        let promise = js_sys::Promise::resolve(&JsValue::NULL);
        // Convert the promise into a `JsFuture`.
        let inner = JsFuture::from(promise);
        NextTick { inner }
    }
}

impl Future for NextTick {
    type Item = ();
    type Error = ();

    fn poll(&mut self) -> Poll<(), ()> {
        // Polling a `NextTick` just forwards to polling if the inner promise is
        // ready.
        match self.inner.poll() {
            Ok(Async::Ready(_)) => Ok(Async::Ready(())),
            Ok(Async::NotReady) => Ok(Async::NotReady),
            Err(_) => unreachable!(
                "We only create NextTick with a resolved inner promise, never \
                 a rejected one, so we can't get an error here"
            ),
        }
    }
}

/// Export a function to JavaScript that does some work in the next tick of the
/// micro task queue!
#[wasm_bindgen]
pub fn schedule_some_work_for_next_tick() -> js_sys::Promise {
    let future = NextTick::new()
        // Do some work...
        .and_then(|_| {
            Ok(42)
        })
        // And then convert the `Item` and `Error` into `JsValue`.
        .map(|result| {
            JsValue::from(result)
        })
        .map_err(|error| {
            let js_error = js_sys::Error::new(&format!("uh oh! {:?}", error));
            JsValue::from(js_error)
        });

    // Convert the `Future<Item = JsValue, Error = JsValue>` into a JavaScript
    // `Promise`!
    future_to_promise(future)
}

Dependencies

~2MB
~42K SLoC