wasm-bindgen-futures

Bridging the gap between Rust Futures and JavaScript Promises

31 releases

✓ Uses Rust 2018 edition

new 0.3.23 Jun 14, 2019
0.3.20 Apr 29, 2019
0.3.17 Mar 22, 2019
0.3.6 Dec 4, 2018
0.3.5 Nov 12, 2018

#17 in WebAssembly

Download history 1365/week @ 2019-03-01 1772/week @ 2019-03-08 1568/week @ 2019-03-15 1204/week @ 2019-03-22 1363/week @ 2019-03-29 1683/week @ 2019-04-05 2011/week @ 2019-04-12 1746/week @ 2019-04-19 1791/week @ 2019-04-26 1988/week @ 2019-05-03 2058/week @ 2019-05-10 3048/week @ 2019-05-17 2107/week @ 2019-05-24 2471/week @ 2019-05-31 2522/week @ 2019-06-07

8,412 downloads per month
Used in 81 crates (20 directly)

MIT/Apache

396KB
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
~35K SLoC