Learn about our RFC process, Open RFC meetings & more.Join in the discussion! »

bs-yarp

0.3.1 • Public • Published

npm Build Status

Yet Another Reason Promise

This project has taken a lot of inspiration the future library. Also many bucklescript/reason Promise libraries exists. However this version focuses on the premise that a promise library should internally prepare for the possibility of failures -> thus Belt.Result.t is integral part of this library.

Install

npm install bs-yarp

And to your bsconfig.json:

"bs-dependencies": [..., "bs-yarp", ...],

Safe to open the whole BsYarp, only singular Promise module is imported:

open BsYarp;

Usage examples

Type:

Promise.t('a)  /* Promise will resolve with ok-value ('a) or with error (exn) */

Create Promise

  • From Js.Promise.t : Promise.fromJs(jsPromise);
  • From a value: Promise.fromValue("example");
    • The given value is internally set as Ok-value.
  • From a Belt.Result.t value: Promise.fromResult(res);
    • Internally set as Ok or Error -value depending on the given result.
  • With Promise.make which uses resolve callback:
    Promise.make(resolve =>
      setTimeout(() => resolve(Result.Ok("example")), 500)
      -> ignore
    );
    
    The resolve callback takes an argument of type Belt.Result.t('a, exn)
  • With Promise.makeWithCb which is more compatible with the node.js callback convention:
    type nodeCb('a, 'e) = (Js.Nullable.t('e), Js.Nullable.t('a)) => unit;
    [@bs.val] [@bs.module "fs"] external readFile: string => string => nodeCb('a, 'e) => unit = "";
    
    Promise.makeWithCb(callback => readFile("example.txt", "utf8", callback));
    
    • The error type is generic 'e here. The makeWithCb will auto-convert any kind of 'e into exn as long as the 'e can be inferred consistently into some type. This is similar to the way reason converts all kinds of errors thrown inside of try() into exn type.
  • API section below contains type descriptions of all the functions.

Action and catch

promise
-> Promise.tapOk(value => Js.log("Example: " ++ value))
-> Promise.catch(e => Js.log("Error: " ++ Js.String.make(e)));

A common pattern where tapOk executes the desired effects for the resolved value or alternatively catch is executed in case of error. The chain terminates with unit (no additional ->ignore needed to terminate the fast forward chain in this case)

Transformations

Promise.fromValue(123)
-> Promise.mapOk(v => (v + 45) * 3)
-> Promise.flatMapOk(v => fnReturningAPromise(v))
-> Promise.tapOk(x => Js.log(x))
-> Promise.toJs()  /* to Js.Promise.t */

About Promise.toJs():

  • Because Js.Promise.t is used underneath and it takes exn types of error values, it means that rejected promises will unavoidably have complex [["Test.SomeError",21],"example"] types of contents in the js side which may seem confusing at first when e.g. logged to application logs.

API:

  • type: t('a)

    • This Promise type. Internal details encapsuled.
  • make: ((Result.t('a, exn) => unit) => unit) => t('a)

    • Make new using resolver.
  • makeWithCb: (((Js.Nullable.t('e), Js.Nullable.t('a)) => unit) => unit) => t('a)

    • Make new with a node callback.
  • fromValue: 'a => t('a)

    • Make new from ok value. Immediately resolved.
  • fromError: exn => t('a)

    • Make new from error value. Immediately resolved as error.
  • fromResult: Result.t('a, exn) => t('a)

    • Make new from result. Immediately resolved as Ok or Error.
  • fromJs: Js.Promise.t('a) => t('a)

    • Make new based on jsPromise. Resolves as Ok when the jsPromise is resolved or as Error if the JsPromise is rejected.
  • fromJsWithErrorConverter: Js.Promise.t('a) => (Js.Promise.error => exn) => t('a)

    • Same as fromJs but you can provide custom error converter (Js.Promise.error => exn)
  • toJs: t('a) => Js.Promise.t('a)

    • Returns a jsPromise. If rejected, the ocaml error (always of type exn) is passed as is.
  • toJsWithErrorConversion: t('a) => Js.Promise.t('a)

    • Returns a jsPromise. If rejected, the ocaml error is internally converted into a js Error (Js.Exn.t) on rejection.
  • tapResult: t('a) => (Result.t('a, exn) => unit) => t('a)

    • With promise, execute the consumer with the internal result when it is resolved. Any exceptions thrown by consumer are ignored. Returns a promise which is identical to the given promise.
  • getResult: t('a) => (Result.t('a, exn) => unit) => unit

    • Like tapResult but without return value.
  • tapOk: t('a) => ('a => unit) => t('a)

    • With promise, execute the consumer with the resolved ok value. Any exceptions thrown by the consumer are ignored. Returns a promise which is identical to the given promise.
  • tapError: t('a) => (exn => unit) => t('a)

    • Similar to tapOk, but error value is passed to the consumer.
  • catch: t('a) => (exn => unit) => unit

    • Like tapError but without return value.
  • mapOk: t('a) => ('a => 'b) => t('b)

    • With promise, map ok-value with the given function. Returned promise will either contain the new ok-value or an error value if the function throws an exception.
  • mapError: t('a) => (exn => exn) => t('a)

    • With promise, map error-value with the given function. If the function throws an exception, that too is catched.
  • mapResult: t('a) => (Result.t('a, exn) => Result.t('b, exn)) => t('b)

    • With promise, map Belt.Result.t into another Belt.Result.t. If function throws an exception it is mapped as Error result.
  • mapOkResult: t('a) => ('a => Result.t('b, exn)) => t('b)

    • With promise, map ok value into Result.t. If function throws an exception it is mapped as Error result.
  • mapErrorResult: t('a) => (exn => Result.t('a, exn)) => t('a)

    • With promise, map error into Result.t. If function throws an exception it is mapped as Error result.
  • flatMap: t('a) => (Result.t('a, exn) => t('b)) => t('b)

    • With promise, bind the function which returns the resulting promise. No exception catching at this level.
  • flatMapOk: t('a) => ('a => t('b)) => t('b)

    • With promise, bind ok value to the function which returns the resulting promise. No exception catching at this level.
  • flatMapError: t('a) => (exn => t('a)) => t('a)

    • With promise, bind error value the function which returns the resulting promise. No exception catching at this level.
  • all: list(t('a)) => t(list('a))

    • Turn list of promises (of homogeneous type) into a promise of list.
  • all2: (t('a), t('b)) => t(('a, 'b))

    • Tuple of heterogeneous promises into a promise of tuple.
  • all3: (t('a), t('b), t('c)) => t(('a, 'b, 'c))

  • all4: (t('a), t('b), t('c), t('d)) => t(('a, 'b, 'c, 'd))

  • all5: (t('a), t('b), t('c), t('d), t('e)) => t(('a, 'b, 'c, 'd, 'e))

  • all6: (t('a), t('b), t('c), t('d), t('e), t('f)) => t(('a, 'b, 'c, 'd, 'e, 'f))

  • map2: t('a) => t('b) => ((Result.t('a, exn), Result.t('b, exn)) => Result.t('z, exn)) => t('z)

    • map2 takes 3 arguments: 2 heterogeneous promises and a bi-function which combines results into a combined result. Returned promise will contain the combined result.
  • map3: t('a) => t('b) => t('c) => ((Result.t('a, exn), Result.t('b, exn), Result.t('c, exn)) => Result.t('z, exn)) => t('z)

  • map4: t('a) => t('b) => t('c) => t('d) => ((Result.t('a, exn), Result.t('b, exn), Result.t('c, exn), Result.t('d, exn)) => Result.t('z, exn)) => t('z)

  • map5: t('a) => t('b) => t('c) => t('d) => t('e) => ((Result.t('a, exn), Result.t('b, exn), Result.t('c, exn), Result.t('d, exn), Result.t('e, exn)) => Result.t('z, exn)) => t('z)

  • map6: t('a) => t('b) => t('c) => t('d) => t('e) => t('f) => ((Result.t('a, exn), Result.t('b, exn), Result.t('c, exn), Result.t('d, exn), Result.t('e, exn), Result.t('f, exn)) => Result.t('z, exn)) => t('z)

Install

npm i bs-yarp

DownloadsWeekly Downloads

2

Version

0.3.1

License

MIT

Unpacked Size

19.5 kB

Total Files

7

Last publish

Collaborators

  • avatar