Fluture
A complete Fantasy Land compatible Future library.
npm install --save fluture
Requires node 5.0.0 or later
Usage
Future.node(done => fs.readFile('package.json', 'utf8', done))
.chain(x => Future.try(() => JSON.parse(x)))
.map(x => x.name)
.fork(console.error, console.log)
Motivation
- A stand-alone Fantasy Future package.
- Async control utilities included.
- Easier debugging than
f(...).fork is not a function
. - Still maintain decent speed.
Documentation
Future
A (monadic) container which represents an eventual value. A lot like Promise but
more principled in that it follows the Fantasy Land algebraic JavaScript
specification.
const eventualThing = Future((reject, resolve) => {
setTimeout(resolve, 500, 'world');
});
eventualThing.fork(console.error, thing => console.log(`Hello ${thing}!`));
of :: b -> Future a b
A constructor that creates a Future containing the given value.
const eventualThing = Future.of('world');
eventualThing.fork(console.error, thing => console.log(`Hello ${thing}!`));
after :: Number -> b -> Future a b
A constructor that creates a Future containing the given value after n milliseconds.
const eventualThing = Future.after(500, 'world');
eventualThing.fork(console.error, thing => console.log(`Hello ${thing}!`));
try :: (Void -> !a | b) -> Future a b
A constructor that creates a Future which resolves with the result of calling
the given function, or rejects with the error thrown by the given function.
const data = {foo: 'bar'}
Future.try(() => data.foo.bar.baz).fork(console.error, console.log)
node :: ((a, b -> Void) -> Void) -> Future a b
A constructor that creates a Future which rejects with the first argument given
to the function, or resolves with the second if the first is not present.
This is a convenience for NodeJS users who wish to easily obtain a Future from
a node style callback API.
Future.node(done => fs.readFile('package.json', 'utf8', done))
.fork(console.error, console.log)
map :: Future a b ~> (b -> c) -> Future a c
Map over the value inside the Future. If the Future is rejected, mapping is not
performed.
Future.of(1).map(x => x + 1).fork(console.error, console.log);
chain :: Future a b ~> (b -> Future a c) -> Future a c
FlatMap over the value inside the Future. If the Future is rejected, chaining is
not performed.
Future.of(1).chain(x => Future.of(x + 1)).fork(console.error, console.log);
ap :: Future a (b -> c) ~> Future a b -> Future a c
Apply the value in the Future to the value in the given Future. If the Future is
rejected, applying is not performed.
Future.of(x => x + 1).ap(Future.of(1)).fork(console.error, console.log);
race :: Future a b -> Future a b -> Future a b
Race two Futures against eachother. Creates a new Future which resolves or
rejects with the resolution or rejection value of the first Future to settle.
Future.race(Future.after(100, 'hello'), Future.after(50, 'bye'))
.fork(console.error, console.log)
const first = futures => futures.reduce(Future.race);
first([
Future.after(100, 'hello'),
Future.after(50, 'bye'),
Future(rej => setTimeout(rej, 25, 'nope'))
])
.fork(console.error, console.log)
Road map
Benchmarks
Simply run node ./bench/<file>
to see how a specific method compares to
implementations in data.task
, ramda-fantasy.Future
and Promise
*.
* Promise is not included in all benchmarks because it tends to make the
process run out of memory.
The name
A conjunction of the acronym to Fantasy Land (FL) and Future. Also "fluture"
means butterfly in Romanian; A creature you might expect to see in Fantasy Land.