1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
//! Converting between JavaScript `Promise`s to Rust `Future`s. //! //! 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`**](./struct.JsFuture.html) //! //! 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`**](./fn.future_to_promise.html) //! //! 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`. //! //! ```rust,no_run //! 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) //! } //! ``` #![cfg_attr(target_feature = "atomics", feature(stdsimd))] #![deny(missing_docs)] use cfg_if::cfg_if; mod legacy_shared; pub use legacy_shared::*; cfg_if! { if #[cfg(target_feature = "atomics")] { /// Contains a thread-safe version of this crate, with Futures 0.1 mod legacy_atomics; pub use legacy_atomics::*; /// Polyfill for `Atomics.waitAsync` function mod wait_async_polyfill; } else { mod legacy; pub use legacy::*; } } #[cfg(feature = "futures_0_3")] cfg_if! { if #[cfg(target_feature = "atomics")] { compile_error!("futures 0.3 support is not implemented with atomics yet"); } else { /// Contains a Futures 0.3 implementation of this crate. pub mod futures_0_3; } }