npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

reason-future

v3.0.0

Published

A lightweight, functional alternative to Js.Promise for ReScript, designed for better composability and error handling.

Downloads

441

Readme

npm Build Status Coverage Status

The Future is Now

Future is a lightweight, functional alternative to Js.Promise for ReScript, designed to make async code more composable and maintainable.

Compatibility

Key Benefits of Using Future Over Promises:

  • Lighter weight – Only ~25 lines of implementation.
  • Simpler – Futures only resolve to a single type (as opposed to resolve and reject types), giving you more flexibility on your error handling.
  • More robust – Futures have sound typing (unlike JS promises).

Installation

First make sure you have rescript >= 11.1.X. Then install with npm:

$ npm install --save reason-future

Then add "reason-future" to your rescript.json dev dependencies:

{
  ...
  "bs-dependencies": [
    "reason-future"
  ]
}

Basic Usage

To create a task, use Future.make. It provides a single resolve function, similar to how Promises work but without a reject:

let futureGreeting = Future.make(resolve => resolve("hi"));

To get the value of a future, use Future.get:

let futureGreeting = Future.make(resolve => resolve("hi"));
futureGreeting->Future.get(x => Js.log("Got value: " ++ x));

/* Alternatively: */

Future.make(resolve => resolve("hi"))
->Future.get(x => Js.log("Got value: " ++ x));

Future.get only retrieves the future value. If you want to transform it to a different value, then you should use Future.map:

/* Shortcut for: let future_A = Future.make(resolve => resolve(99)); */
let future_A = Future.value(99);

let future_B = future_A->Future.map(n => n + 1);


future_A->Future.get(n => Js.log(n)); /* logs: 99 */

future_B->Future.get(n => Js.log(n)); /* logs: 100 */

And finally, if you map a future and return another future, you probably want to flatMap instead:

let futureNum = Future.value(50);

let ft_a = futureNum->Future.map(n => Future.value(n + 10));
let ft_b = futureNum->Future.flatMap(n => Future.value(n + 20));

/* ft_a has type future(future(int)) – probably not what you want. */
/* ft_b has type future(int) */

API

Core functions. Note: _ represents the future itself as inserted by -> (the pipe operator).

  • Future.make(resolver) - Create a new, potentially-async future.
  • Future.value(x) - Create a new future with a plain value (synchronous).
  • Future.map(_,fn) - Transform a future value into another value
  • Future.flatMap(_,fn) - Transform a future value into another future value
  • Future.get(_,fn) - Get the value of a future
  • Future.tap(_,fn) - Do something with the value of a future without changing it. Returns the same future so you can continue using it in a pipeline. Convenient for side effects such as console logging.
  • Future.all(_,fn) - Turn a list of futures into a future of a list. Used when you want to wait for a collection of futures to complete before doing something (equivalent to Promise.all in Javascript).

Result

Convenience functions when working with a future Result. Note: _ represents the future itself as inserted by -> (the pipe operator).

Note 2: The terms Result.Ok and Result.Error in this context are expected to be read as Ok and Error.

  • Future.mapOk(_,fn) - Transform a future value into another value, but only if the value is an Result.Ok. Similar to Promise.prototype.then
  • Future.mapError(_,fn) - Transform a future value into another value, but only if the value is an Result.Error. Similar to Promise.prototype.catch
  • Future.tapOk(_,fn) - Do something with the value of a future without changing it, but only if the value is a Ok. Returns the same future. Convenience for side effects such as console logging.
  • Future.tapError(_,fn) - Same as tapOk but for Result.Error

The following are more situational:

  • Future.flatMapOk(_, fn) - Transform a future Result.Ok into a future Result. Flattens the inner future.
  • Future.flatMapError(_, fn) - Transform a future Result.Error into a future Result. Flattens the inner future.

FutureJs

Convenience functions for interop with JavaScript land.

  • FutureJs.fromPromise(promise, errorTransformer)
    • promise is the RescriptCore.Promise.t('a) that will be transformed into a Future.t(result('a, 'e))
    • errorTransformer allows you to determine how Promise.error objects will be transformed before they are returned wrapped within a Error. This allows you to implement the error handling method which best meets your application's needs.
  • FutureJs.toPromise(future)
    • future is any Future.t('a) which is transformed into a RescriptCore.Promise.t('a). Always resolves, never rejects the promise.
  • FutureJs.resultToPromise(future)
    • future is the Future.t(result('a, 'e)) which is transformed into a RescriptCore.Promise.t('a). Resolves the promise on Ok result and rejects on Error result.

Example use:

/*
  This error handler is super simple; you will probably want
  to write something more sophisticated in your app.
*/
let handleError = Js.String.make;

somePromiseGetter()
->FutureJs.fromPromise(handleError)
->Future.tap(value => Js.log2("It worked!", value))
->Future.tapError(err => Js.log2("uh on", err));

See Composible Error Handling in OCaml for several strategies that you may employ.

Stack Safety

By default this library is not stack safe, you will recieve a 'Maximum call stack size exceeded' error if you recurse too deeply. You can opt into stack safety by passing an optional parameter to the constructors of trampoline. This has a slight overhead. For example:

let stackSafe = Future.make(~executor=`trampoline, resolver);
let stackSafeValue = Future.value(~executor=`trampoline, "Value");

TODO

Build

npm run build

Build + Watch

npm run start

Test

npm test

Editor

If you use vscode, Press Windows + Shift + B it will build automatically