11
61%
MIT
Reason bindings for Fluture.js

bs-fluture

ReasonML bindings for Fluture.

NOTE: v1+ of bs-fluture is only compatible with v12+ of Fluture (see v12's Breaking Changes document for more details). If you are using v11 of Fluture or lower, you must use v0.x of bs-fluture.

This library of bindings does not currently cover 100% of the Fluture API, although it does cover the vast majority of the commonly-used API, especially for the ReScript/ReasonML context. Please file an issue if one of the bindings is missing, wrong or it isn't working for you in general.

Justification

Futures, as provided by Fluture, give the following benefits over Promises:

  • Futures are lazy, rather than eager. Creating a future doesn't actually perform the async task – that only happens when you consume the future with e.g. fork(). Promises, on the other hand, perform their async task as soon as they are created. If you want a Promise that you can pass around without actually running it, you have to wrap it in a function, introducing more boilerplate.
  • Cancellation is a built-in feature of futures.
  • Unlike Promises (even in Reason!), Futures explicitly type their error states.

Installation

npm install --save bs-fluture

Then add bs-fluture to bs-dependencies in your bsconfig.json:

{
  "bs-dependencies": ["bs-fluture"]
}

Usage

  • RE
  • ML
let future =
  BsFluture.make((reject, resolve) => {
    let timeoutId =
      Js.Global.setTimeout(
        () =>
          if (Random.bool()) {
            resolve("success");
          } else {
            reject("error");
          },
        30,
      );

    /** EITHER return a wrapped cancellation function ... */
    BsFluture.Cancel(() => Js.Global.clearTimeout(timeoutId));
    /** ... OR return NoCancel if there is no way to clean up. */
    BsFluture.NoCancel;
  });

let cancelFuture =
  future
  |> BsFluture.fork(error => Js.Console.error(error), response => Js.log(response));

/**
 * Due to runtime type-checking in Fluture,
 * the cancellation function must be explicitly uncurried.
 */
cancelFuture(.);
let future =
  BsFluture.make
    (fun reject  ->
       fun resolve  ->
         let timeoutId =
           Js.Global.setTimeout
             (fun ()  ->
                if Random.bool () then resolve "success" else reject "error")
             30 in
         ((BsFluture.Cancel (((fun ()  -> Js.Global.clearTimeout timeoutId))))
         [@ocaml.doc " EITHER return a wrapped cancellation function ... "]
         [@explicit_arity ]);
         ((BsFluture.NoCancel)[@ocaml.doc
                                " ... OR return NoCancel if there is no way to clean up. "]))
let cancelFuture =
  future |>
    (BsFluture.fork (fun error  -> Js.Console.error error)
       (fun response  -> Js.log response))
let _ = cancelFuture ()[@@bs ][@@ocaml.doc
                                "\n * Due to runtime type-checking in Fluture,\n * the cancellation function must be explicitly uncurried.\n "]

let-anything

This package is compatible with let-anything – use it like this:

  • RE
  • ML
let getDefaultUsername = (futureEmail: BsFluture.t(Js.Exn.t, string)) => {
  let%BsFluture email = futureEmail;
  let name = Js.String.split(email, "@")[0];
  BsFluture.resolve(name);
};
let getDefaultUsername (futureEmail : (Js.Exn.t,string) BsFluture.t) =
  [%BsFluture
    let email = futureEmail in
    let name = (Js.String.split email "@").(0) in BsFluture.resolve name]