Socket
Socket
Sign inDemoInstall

fluture

Package Overview
Dependencies
Maintainers
1
Versions
109
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fluture - npm Package Compare versions

Comparing version 5.0.0 to 6.0.0

index.es.js

51

package.json
{
"name": "fluture",
"version": "5.0.0",
"version": "6.0.0",
"description": "FantasyLand compliant (monadic) alternative to Promises",
"main": "fluture.js",
"main": "index.js",
"module": "index.es.js",
"files": [
"es5.js"
"src",
"index.es.js"
],
"repository": "https://github.com/fluture-js/Fluture.git",
"scripts": {
"build": "babel fluture.js -o es5.js",
"clean": "rimraf npm-debug.log coverage",
"lint": "eslint fluture.js test",
"build": "rollup -c",
"clean": "rimraf npm-debug.log coverage index.js index.test.js",
"lint": "eslint src test index.es.js README.md",
"lint:fix": "npm run lint -- --fix",

@@ -19,8 +21,7 @@ "lint:readme": "remark --no-stdout --frail -u remark-validate-links README.md",

"toc": "node scripts/toc.js",
"test": "npm run test:all && npm run test:coverage && codecov",
"test": "npm run lint && npm run lint:readme && npm run test:unit",
"test:opt": "node --allow-natives-syntax --trace-opt --trace-deopt --trace-inlining scripts/test-opt",
"test:mem": "node scripts/test-mem",
"test:all": "npm run lint && npm run lint:readme && npm run test:unit",
"test:unit": "_mocha --ui bdd --reporter list --check-leaks --full-trace test/**.test.js",
"test:coverage": "npm run clean && istanbul cover --report html _mocha -- --ui bdd --reporter dot --check-leaks --bail test/**.test.js"
"test:unit": "rollup -c rollup.config.test.js && mocha --require source-map-support/register --reporter test/reporter.js index.test.js",
"test:coverage": "codecov"
},

@@ -56,30 +57,36 @@ "author": "Aldwin Vlasblom <aldwin.vlasblom@gmail.com> (https://github.com/Avaq)",

"dependencies": {
"concurrify": "^0.1.0",
"concurrify": "^1.0.0",
"inspect-f": "^1.2.0",
"sanctuary-type-classes": "^3.0.0",
"sanctuary-type-identifiers": "^1.0.0"
"sanctuary-type-classes": "^5.1.0",
"sanctuary-type-identifiers": "^2.0.0"
},
"devDependencies": {
"babel-cli": "^6.18.0",
"babel-preset-latest": "^6.16.0",
"benchmark": "^2.1.0",
"chai": "^3.4.0",
"codecov": "^1.0.1",
"codecov": "^2.2.0",
"data.task": "^3.0.0",
"denque": "^1.1.1",
"eslint": "^3.0.1",
"eslint-config-warp": "^1.2.0",
"eslint-plugin-markdown": "^1.0.0-beta.6",
"fantasy-land": "^3.0.0",
"fun-task": "^1.5.1",
"istanbul": "^0.4.2",
"jsverify": "^0.7.1",
"lazy-either": "^1.0.3",
"istanbul": "^0.4.5",
"jsverify": "^0.8.2",
"lodash.curry": "^4.1.1",
"markdown-toc": "^1.0.2",
"mocha": "^3.0.2",
"ramda-fantasy": "^0.7.0",
"remark-cli": "^2.1.0",
"remark-validate-links": "^5.0.0",
"ramda": "^0.23.0",
"ramda-fantasy": "^0.8.0",
"remark-cli": "^3.0.1",
"remark-validate-links": "^6.0.0",
"rimraf": "^2.4.3",
"rollup": "^0.41.6",
"rollup-plugin-buble": "^0.15.0",
"rollup-plugin-istanbul": "^1.1.0",
"rollup-plugin-multi-entry": "^2.0.1",
"rollup-plugin-uglify": "^1.0.1",
"source-map-support": "^0.4.14",
"xyz": "^2.0.1"
}
}

@@ -20,2 +20,3 @@ # [![Fluture](logo.png)](#butterfly)

* [Resource management utilities](#resource-management).
* [Stack safe composition and recursion](#stack-safety).
* Great integration with functional libraries such as [Sanctuary][S].

@@ -34,9 +35,36 @@ * A pleasant debugging experience through informative error messages.

### In ES5 or older environments
Fluture depends on these functions being present:
[`Object.create`][JS:Object.create],
[`Object.assign`][JS:Object.assign] and [`Array.isArray`][JS:Array.isArray].
You may need to polyfill one or more.
<!-- eslint-disable no-var -->
```js
const fs = require('fs');
const Future = require('fluture');
var fs = require('fs');
var Future = require('fluture');
var getPackageName = function(file){
return Future.node(function(done){ fs.readFile(file, 'utf8', done) })
.chain(Future.encase(JSON.parse))
.map(function(x){ return x.name });
};
getPackageName('package.json')
.fork(console.error, console.log);
//> "fluture"
```
### In ES6 or newer environments
The `package.json` sets a `module`-field for build-tools like [Rollup][].
```js
import {readFile} from 'fs';
import {node, encase} from 'fluture';
const getPackageName = file =>
Future.node(done => fs.readFile(file, 'utf8', done))
.chain(Future.encase(JSON.parse))
node(done => { readFile(file, 'utf8', done) })
.chain(encase(JSON.parse))
.map(x => x.name);

@@ -49,4 +77,2 @@

For front-end applications and node <v4, please use `require('fluture/es5')`.
## Table of contents

@@ -57,46 +83,47 @@

- [Documentation](#documentation)
1. [Type signatures](#type-signatures)
1. [Creating Futures](#creating-futures)
* [Future](#future)
* [of](#of)
* [never](#never)
* [reject](#reject)
* [after](#after)
* [rejectAfter](#rejectafter)
* [try](#try)
* [encase](#encase)
* [fromPromise](#frompromise)
* [node](#node)
* [chainRec](#chainrec)
1. [Transforming Futures](#transforming-futures)
* [map](#map)
* [bimap](#bimap)
* [chain](#chain)
* [ap](#ap)
* [swap](#swap)
1. [Error handling](#error-handling)
* [mapRej](#maprej)
* [chainRej](#chainrej)
* [fold](#fold)
1. [Resource management](#resource-management)
* [hook](#hook)
* [finally](#finally)
1. [Consuming Futures](#consuming-futures)
* [fork](#fork)
* [value](#value)
* [promise](#promise)
1. [Parallelism](#parallelism)
* [race](#race)
* [and](#and)
* [or](#or)
* [both](#both)
* [parallel](#parallel)
* [ConcurrentFuture](#concurrentfuture)
1. [Utility functions](#utility-functions)
* [isFuture](#isfuture)
* [cache](#cache)
* [do](#do)
1. [Sanctuary](#sanctuary)
1. [Futurization](#futurization)
- [Benchmarks](#benchmarks)
1. [Type signatures](#type-signatures)
1. [Stack safety](#stack-safety)
1. [Creating Futures](#creating-futures)
* [Future](#future)
* [of](#of)
* [reject](#reject)
* [after](#after)
* [rejectAfter](#rejectafter)
* [cache](#cache)
* [do](#do)
* [try](#try)
* [encase](#encase)
* [encaseP](#encasep)
* [node](#node)
1. [Transforming Futures](#transforming-futures)
* [map](#map)
* [bimap](#bimap)
* [chain](#chain)
* [swap](#swap)
* [mapRej](#maprej)
* [chainRej](#chainrej)
* [fold](#fold)
1. [Combining Futures](#combining-futures)
* [ap](#ap)
* [and](#and)
* [or](#or)
1. [Resource management](#resource-management)
* [hook](#hook)
* [finally](#finally)
1. [Consuming Futures](#consuming-futures)
* [fork](#fork)
* [value](#value)
* [promise](#promise)
1. [Parallelism](#parallelism)
* [race](#race)
* [both](#both)
* [parallel](#parallel)
* [ConcurrentFuture](#concurrentfuture)
1. [Utility functions](#utility-functions)
* [isFuture](#isfuture)
* [never](#never)
* [isNever](#isnever)
1. [Sanctuary](#sanctuary)
1. [Futurization](#futurization)
1. [Casting Futures](#casting-futures)
- [Butterfly](#butterfly)

@@ -109,9 +136,8 @@

Fluture implements [FantasyLand 1][FL1], [FantasyLand 2][FL2],
[FantasyLand 3][FL3] and [Static Land][6] compatible `Functor`, `Bifunctor`,
`Apply`, `Applicative`, `Chain`, `ChainRec` and `Monad`.
* `Future` implements [Fantasy Land][FL] and [Static Land][6] -compatible
`Bifunctor`, `Monad` and `ChainRec` (`of`, `ap`, `map`, `bimap`, `chain`, `chainRec`).
All versions of Fantasy Land are supported.
* `Future.Par` implements [Fantasy Land 3][FL] `Alternative` (`of`, `zero`, `map`, `ap`, `alt`).
* The Future representative contains a `@@type` property for [Sanctuary Type Identifiers][STI].
FantasyLand 0.x is *mostly* supported. Everything but `Apply` (`ap`) is, this
means that dispatchers to FantasyLand 0.x `ap` will not work.
## Documentation

@@ -143,2 +169,28 @@

### Stack safety
Fluture interprets your transformations in a stack safe way. This means that
none of the following operations raise `RangeError: Maximum call stack size exceeded`:
```js
const add1 = x => x + 1;
let m = Future.of(1);
for(let i = 0; i < 100000; i++){
m = m.map(add1);
}
m.fork(console.error, console.log);
//> 100001
```
```js
const m = (function recur(x){
const mx = Future.of(x + 1);
return x < 100000 ? mx.chain(recur) : mx;
}(1));
m.fork(console.error, console.log);
//> 100001
```
### Creating Futures

@@ -183,8 +235,2 @@

#### never
##### `.never :: Future a a`
A Future that never settles. Can be useful as an initial value when reducing
with [`race`](#race), for example.
#### reject

@@ -218,4 +264,77 @@ ##### `.reject :: a -> Future a _`

#### cache
##### `.cache :: Future a b -> Future a b`
Returns a Future which caches the resolution value of the given Future so that
whenever it's forked, it can load the value from cache rather than reexecuting
the chain.
```js
const {readFile} = require('fs');
const eventualPackage = Future.cache(
Future.node(done => {
console.log('Reading some big data');
readFile('package.json', 'utf8', done);
})
);
eventualPackage.fork(console.error, console.log);
//> "Reading some big data"
//> "{...}"
eventualPackage.fork(console.error, console.log);
//> "{...}"
```
#### do
##### `.do :: (() -> Iterator) -> Future a b`
##### `.go :: (() -> Iterator) -> Future a b`
A specialized version of [fantasy-do][4] which works only for Futures, but has
the advantage of type-checking and not having to pass `Future.of`. Another
advantage is that the returned Future can be forked multiple times, as opposed
to with a general `fantasy-do` solution, where forking the Future a second time
behaves erroneously.
Takes a function which returns an [Iterator](#type-signatures), commonly a
generator-function, and chains every produced Future over the previous.
This allows for writing sequential asynchronous code without the pyramid of
doom. It's known as "coroutines" in Promise land, and "do-notation" in Haskell
land.
```js
Future.do(function*(){
const thing = yield Future.after(300, 'world');
const message = yield Future.after(300, 'Hello ' + thing);
return message + '!';
})
.fork(console.error, console.log);
//After 600ms:
//> "Hello world!"
```
Error handling is slightly different in do-notation, you need to [`fold`](#fold)
the error into your control domain, I recommend folding into an [`Either`][S:Either]:
```js
const attempt = Future.fold(S.Left, S.Right);
const ajaxGet = url => Future.reject('Failed to load ' + url);
Future.do(function*(){
const e = yield attempt(ajaxGet('/message'));
return S.either(
e => `Oh no! ${e}`,
x => `Yippee! ${x}`,
e
);
})
.fork(console.error, console.log);
//> "Oh no! Failed to load /message"
```
This function has an alias `go`, for environments in which `do` is a reserved word.
#### try
##### `.try :: (() -> !a | b) -> Future a b`
##### `.attempt :: (() -> !a | b) -> Future a b`

@@ -228,8 +347,10 @@ Creates a Future which resolves with the result of calling the given function,

```js
const data = {foo: 'bar'}
const data = {foo: 'bar'};
Future.try(() => data.foo.bar.baz)
.fork(console.error, console.log)
.fork(console.error, console.log);
//> [TypeError: Cannot read property 'baz' of undefined]
```
This function has an alias `attempt`, for environments in which `try` is a reserved word.
#### encase

@@ -245,5 +366,5 @@ ##### `.encase :: (a -> !e | r) -> a -> Future e r`

```js
const data = '{"foo" = "bar"}'
const data = '{"foo" = "bar"}';
Future.encase(JSON.parse, data)
.fork(console.error, console.log)
.fork(console.error, console.log);
//! [SyntaxError: Unexpected token =]

@@ -257,5 +378,5 @@ ```

```js
const data = '{"foo" = "bar"}'
const safeJsonParse = Future.encase(JSON.parse)
safeJsonParse(data).fork(console.error, console.log)
const data = '{"foo" = "bar"}';
const safeJsonParse = Future.encase(JSON.parse);
safeJsonParse(data).fork(console.error, console.log);
//! [SyntaxError: Unexpected token =]

@@ -267,18 +388,19 @@ ```

#### fromPromise
##### `.fromPromise :: (a -> Promise e r) -> a -> Future e r`
##### `.fromPromise2 :: (a, b -> Promise e r) -> a -> b -> Future e r`
##### `.fromPromise3 :: (a, b, c -> Promise e r) -> a -> b -> c -> Future e r`
#### encaseP
##### `.tryP` :: (a -> Promise e r) -> Future e r
##### `.encaseP :: (a -> Promise e r) -> a -> Future e r`
##### `.encaseP2 :: (a, b -> Promise e r) -> a -> b -> Future e r`
##### `.encaseP3 :: (a, b, c -> Promise e r) -> a -> b -> c -> Future e r`
Allows Promise-returning functions to be turned into Future-returning functions.
Takes a function which returns a Promise, and a value, and returns a Future
which calls the function to produce the Promise, and resolves with the Promise
resolution value, or rejects with the Promise rejection reason.
Takes a function which returns a Promise, and a value, and returns a Future.
When forked, the Future calls the function with the value to produce the Promise,
and resolves with its resolution value, or rejects with its rejection reason.
```js
const fetchf = Future.fromPromise(fetch);
const fetchf = Future.encaseP(fetch);
fetchf('https://api.github.com/users/Avaq')
.chain(res => Future.fromPromise(_ => res.json(), 0))
.chain(res => Future.tryP(_ => res.json()))
.map(user => user.name)

@@ -289,4 +411,4 @@ .fork(console.error, console.log);

Furthermore; `fromPromise2` and `fromPromise3` are binary and ternary versions
of `fromPromise`, applying two or three arguments to the given function respectively.
Furthermore; `encaseP2` and `encaseP3` are binary and ternary versions
of `encaseP`, applying two or three arguments to the given function respectively.

@@ -304,27 +426,8 @@ #### node

```js
Future.node(done => fs.readFile('package.json', 'utf8', done))
.fork(console.error, console.log)
const {readFile} = require('fs');
Future.node(done => readFile('package.json', 'utf8', done))
.fork(console.error, console.log);
//> "{...}"
```
#### chainRec
##### `.chainRec :: ((b -> Next, c -> Done, b) -> Future a Iteration) -> b -> Future a c`
Stack- and memory-safe asynchronous "recursion" based on [FantasyLand ChainRec][FL:chainrec].
Calls the given function with the initial value (as third argument), and expects
a Future of an [Iteration](#type-signatures). If the Iteration is incomplete
(`{done: false}`), then the function is called again with the Iteration value
until it returns a Future of a complete (`{done: true}`) Iteration.
For convenience and interoperability, the first two arguments passed to the
function are functions for creating an incomplete Iteration, and for creating a
complete Iteration, respectively.
```js
Future.chainRec((next, done, x) => Future.of(x < 1000000 ? next(x + 1) : done(x)), 0)
.fork(console.error, console.log);
//> 1000000
```
### Transforming Futures

@@ -386,23 +489,2 @@

Note that, due to its lazy nature, the stack and/or heap will slowly fill up as
you chain more over the same structure. It's therefore recommended that you use
[`chainRec`](#chainrec) in cases where you wish to `chain` recursively or
traverse a large list (10000+ items).
#### ap
##### `#ap :: Future a b ~> Future a (b -> c) -> Future a c`
##### `.ap :: Apply m => m (a -> b) -> m a -> m b`
Applies the function contained in the right-hand Future or Apply to the value
contained in the left-hand Future or Apply. If one of the Futures rejects the
resulting Future will also be rejected. To learn more about the exact behaviour
of `ap`, check out its [spec][FL:apply].
```js
Future.of(1)
.ap(Future.of(x => x + 1))
.fork(console.error, console.log);
//> 2
```
#### swap

@@ -422,8 +504,2 @@ ##### `#swap :: Future a b ~> Future b a`

### Error handling
Functions listed under this category allow you to get at or transform the
rejection reason in Futures, or even coerce Futures back into the resolution
branch in several different ways.
#### mapRej

@@ -437,6 +513,5 @@ ##### `#mapRej :: Future a b ~> (a -> c) -> Future c b`

```js
Future.reject(new Error('It broke!')).mapRej(err => {
return new Error('Some extra info: ' + err.message);
})
.fork(console.error, console.log)
Future.reject(new Error('It broke!'))
.mapRej(err => new Error('Some extra info: ' + err.message))
.fork(console.error, console.log);
//! [Some extra info: It broke!]

@@ -455,5 +530,5 @@ ```

console.error(err);
return Future.of('All is good')
return Future.of('All is good');
})
.fork(console.error, console.log)
.fork(console.error, console.log);
//> "All is good"

@@ -485,2 +560,72 @@ ```

### Combining Futures
#### ap
##### `#ap :: Future a (b -> c) ~> Future a b -> Future a c`
##### `.ap :: Apply m => m (a -> b) -> m a -> m b`
Applies the function contained in the left-hand Future or Apply to the value
contained in the right-hand Future or Apply. If one of the Futures rejects the
resulting Future will also be rejected.
```js
Future.of(x => y => x + y)
.ap(Future.of(1))
.ap(Future.of(2))
.fork(console.error, console.log);
//> 3
```
Note that even though `#ap` does *not* conform to the latest [spec][FL:apply],
the hidden `fantasy-land/ap`-method *does*. Therefore Future remains fully
compliant to Fantasy Land.
#### and
##### `#and :: Future a b ~> Future a b -> Future a b`
##### `.and :: Future a b -> Future a b -> Future a b`
Logical and for Futures.
Returns a new Future which either rejects with the first rejection reason, or
resolves with the last resolution value once and if both Futures resolve. This
behaves analogously to how JavaScript's *and*-operator does.
<!-- eslint-disable no-undef -->
```js
//An asynchronous version of:
//isResolved() && getValue();
isResolved().and(getValue());
```
```js
//Asynchronous "all", where the resulting Future will be the leftmost to reject:
const all = ms => ms.reduce(Future.and, Future.of(true));
all([Future.after(20, 1), Future.of(2)]).value(console.log);
//> 2
```
#### or
##### `#or :: Future a b ~> Future a b -> Future a b`
##### `.or :: Future a b -> Future a b -> Future a b`
Logical or for Futures.
Returns a new Future which either resolves with the first resolution value, or
rejects with the last rejection value once and if both Futures reject. This
behaves analogously to how JavaScript's *or*-operator does.
<!-- eslint-disable no-undef -->
```js
//An asynchronous version of:
//planA() || planB();
planA().or(planB());
```
```js
//Asynchronous "any", where the resulting Future will be the leftmost to resolve:
const any = ms => ms.reduce(Future.or, Future.reject('empty list'));
any([Future.reject(1), Future.after(20, 2), Future.of(3)]).value(console.log);
//> 2
```
### Resource management

@@ -492,14 +637,13 @@

#### hook
##### `#hook :: Future a b ~> (b -> Future a c) -> (b -> Future a d) -> Future a d`
##### `.hook :: Future a b -> (b -> Future a c) -> (b -> Future a d) -> Future a d`
Much like [`chain`](#chain), but takes a "dispose" operation first, which runs
*after* the second settles (successfully or unsuccessfully). So the signature is
like `hook(acquire, dispose, consume)`, where `acquire` is a Future which might
create connections, open file handlers, etc. `dispose` is a function that takes
the result from `acquire` and should be used to clean up (close connections etc)
and `consume` also takes the result from `acquire`, and may be used to perform
any arbitrary computations using the resource. The resolution value of `dispose`
is ignored.
Allows a Future-returning function to be decorated with resource acquistion
and disposal. The signature is like `hook(acquire, dispose, consume)`, where
`acquire` is a Future which might create connections, open file handlers, etc.
`dispose` is a function that takes the result from `acquire` and should be used
to clean up (close connections etc) and `consume` also takes the result from
`acquire`, and may be used to perform any arbitrary computations using the
resource. The resolution value of `dispose` is ignored.
<!-- eslint-disable no-undef -->
```js

@@ -514,3 +658,3 @@ const withConnection = Future.hook(

)
.fork(console.error, console.log)
.fork(console.error, console.log);
```

@@ -524,2 +668,3 @@

<!-- eslint-disable no-unused-vars -->
```js

@@ -546,3 +691,5 @@ const closeConnection = conn => Future((rej, res) => {

##### `#finally :: Future a b ~> Future a c -> Future a b`
##### `#lastly :: Future a b ~> Future a c -> Future a b`
##### `.finally :: Future a c -> Future a b -> Future a b`
##### `.lastly :: Future a c -> Future a b -> Future a b`

@@ -556,3 +703,3 @@ Run a second Future after the first settles (successfully or unsuccessfully).

.finally(Future.of('All done!').map(console.log))
.fork(console.error, console.log)
.fork(console.error, console.log);
//> "All done!"

@@ -569,5 +716,5 @@ //> "Hello"

Future.fork(console.error, console.log)
])
]);
program('Hello')
program('Hello');
//> "All done!"

@@ -581,2 +728,4 @@ //> "Hello"

This function has an alias `lastly`, for environments in which `finally` is a reserved word.
### Consuming Futures

@@ -631,3 +780,3 @@

.fold(S.Left, S.Right)
.value(console.log)
.value(console.log);
//> Left([Error: It broke])

@@ -669,3 +818,3 @@ ```

.race(Future.after(50, 'bye'))
.fork(console.error, console.log)
.fork(console.error, console.log);
//> "bye"

@@ -679,60 +828,6 @@

])
.fork(console.error, console.log)
.fork(console.error, console.log);
//! "nope"
```
#### and
##### `#and :: Future a b ~> Future a b -> Future a b`
##### `.and :: Future a b -> Future a b -> Future a b`
Logical and for Futures.
Returns a new Future which either rejects with the first rejection reason, or
resolves with the last resolution value once and if both Futures resolve.
This behaves analogues to how JavaScript's and operator does, except both
Futures run simultaneously, so it is *not* short-circuited. That means that
if the second has side-effects, they will run (and possibly be cancelled) even
if the first rejects.
```js
//An asynchronous version of:
//const result = isResolved() && getValue();
const result = isResolved().and(getValue());
//Asynchronous "all", where the resulting Future will be the leftmost to reject:
const all = ms => ms.reduce(Future.and, Future.of(true));
all([Future.after(20, 1), Future.of(2)]).value(console.log);
//> 2
```
#### or
##### `#or :: Future a b ~> Future a b -> Future a b`
##### `.or :: Future a b -> Future a b -> Future a b`
Logical or for Futures.
Returns a new Future which either resolves with the first resolution value, or
rejects with the last rejection value once and if both Futures reject.
This behaves analogues to how JavaScript's or operator does, except both
Futures run simultaneously, so it is *not* short-circuited. That means that
if the second has side-effects, they will run even if the first resolves.
```js
//An asynchronous version of:
//const result = planA() || planB();
const result = planA().or(planB());
//Asynchronous "any", where the resulting Future will be the leftmost to resolve:
const any = ms => ms.reduce(Future.or, Future.reject('empty list'));
any([Future.reject(1), Future.after(20, 2), Future.of(3)]).value(console.log);
//> 2
```
In the example, assume both plans return Futures. Both plans are executed in
parallel. If `planA` resolves, the returned Future will resolve with its value.
If `planA` fails there is always `planB`. If both plans fail then the returned
Future will also reject using the rejection reason of `planB`.
#### both

@@ -746,7 +841,7 @@ ##### `#both :: Future a b ~> Future a b -> Future a b`

```js
Future.parallel(2, [a, b])
===
Future.both(a, b)
===
a.both(b)
const a = Future.of('a');
const b = Future.of('b');
Future.both(a, b).fork(console.error, console.log);
//> ['a', 'b']
```

@@ -787,3 +882,3 @@

const stabalizedFutures = instableFutures.map(Future.fold(S.Left, S.Right))
const stabalizedFutures = instableFutures.map(Future.fold(S.Left, S.Right));

@@ -800,3 +895,3 @@ Future.parallel(Infinity, stabalizedFutures).fork(console.error, console.log);

[`concurrify`][concurrify] to `Future`. It provides a mechanism for constructing
a [FantasyLand `Alternative`][FL:alternative] from a member of `Future`. This
a [Fantasy Land `Alternative`][FL:alternative] from a member of `Future`. This
allows Futures to benefit from the Alternative Interface, which includes

@@ -823,9 +918,12 @@ parallel `ap`, `zero` and `alt`.

//We can make use of parallel apply
seq(ap(parx, parf)).value(console.log) //> 2
seq(ap(parx, parf)).value(console.log);
//> 2
//Or concurrent sequencing
seq(sequence(Par, [parx, parf])).value(console.log) //> [x, f]
seq(sequence(Par, [parx, parf])).value(console.log);
//> [x, f]
//Or racing with alternative
seq(alt(zero(Par), parx)).value(console.log) //> 1
seq(alt(zero(Par), parx)).value(console.log);
//> 1
```

@@ -839,86 +937,33 @@

Returns true for [Futures](#type-signatures) and false for everything else. This
function (and [`S.is`][S:is]) also return `true` for instances of Future that were
created within other contexts. It is therefore recommended to use this over
function (and [`S.is`][S:is]) also return `true` for instances of Future that
were created within other contexts. It is therefore recommended to use this over
`instanceof`, unless your intent is to explicitly check for Futures created
using the exact `Future` constructor you're testing against.
<!-- eslint-disable no-unused-expressions -->
```js
const Future1 = require('/path/to/fluture');
const Future2 = require('/other/path/to/fluture');
const noop = () => {};
const m1 = Future1(noop);
Future1.isFuture(m1) === (m1 instanceof Future1);
//> true
const m2 = Future2(noop);
Future1.isFuture(m2) !== (m2 instanceof Future1);
Future1.isFuture(m2) === (m2 instanceof Future1);
//> false
```
#### cache
##### `.cache :: Future a b -> Future a b`
#### never
##### `.never :: Future a a`
Returns a Future which caches the resolution value of the given Future so that
whenever it's forked, it can load the value from cache rather than reexecuting
the chain.
A Future that never settles. Can be useful as an initial value when reducing
with [`race`](#race), for example.
```js
const eventualPackage = Future.cache(
Future.node(done => {
console.log('Reading some big data');
fs.readFile('package.json', 'utf8', done)
})
);
#### isNever
##### `.isNever :: a -> Boolean`
eventualPackage.fork(console.error, console.log);
//> "Reading some big data"
//> "{...}"
Returns `true` if the given input is a `never`.
eventualPackage.fork(console.error, console.log);
//> "{...}"
```
#### do
##### `.do :: (() -> Iterator) -> Future a b`
A specialized version of [fantasy-do][4] which works only for Futures, but has
the advantage of type-checking and not having to pass `Future.of`. Another
advantage is that the returned Future can be forked multiple times, as opposed
to with a general `fantasy-do` solution, where forking the Future a second time
behaves erroneously.
Takes a function which returns an [Iterator](#type-signatures), commonly a
generator-function, and chains every produced Future over the previous.
This allows for writing sequential asynchronous code without the pyramid of
doom. It's known as "coroutines" in Promise land, and "do-notation" in Haskell
land.
```js
Future.do(function*(){
const thing = yield Future.after(300, 'world');
const message = yield Future.after(300, 'Hello ' + thing);
return message + '!';
})
.fork(console.error, console.log)
//After 600ms:
//> "Hello world!"
```
Error handling is slightly different in do-notation, you need to [`fold`](#fold)
the error into your control domain, I recommend folding into an [`Either`][S:Either]:
```js
const attempt = Future.fold(S.Left, S.Right);
const ajaxGet = url => Future.reject('Failed to load ' + url);
Future.do(function*(){
const e = yield attempt(ajaxGet('/message'));
return S.either(
e => `Oh no! ${e}`,
x => `Yippee! ${x}`,
e
);
})
.fork(console.error, console.log);
//> "Oh no! Failed to load /message"
```
### Sanctuary

@@ -979,7 +1024,21 @@

## Benchmarks
### Casting Futures
Simply run `node ./bench/<file>` to see how a specific method compares to
implementations in `data.task` and `ramda-fantasy.Future`.
Sometimes you may need to convert one Future to another, for example when the
Future was created by another package, or an incompatible version of Fluture.
When [`isFuture`](#isfuture) returns `false`, a conversion is necessary. Usually
the most concise way of doing this is as follows:
```js
const NoFuture = require('incompatible-future');
const incompatible = NoFuture.of('Hello');
//Cast the incompatible Future to our version of Future:
const compatible = Future(incompatible.fork.bind(incompatible));
compatible.both(Future.of('world')).value(console.log);
//> ["Hello", "world"]
```
## Butterfly

@@ -991,6 +1050,7 @@

Credits for the logo go to [Erik Fuente][8].
----
Thanks to [Erik Fuente][8] for the logo, and [WEAREREASONABLEPEOPLE][9] for
sponsoring the project.
[MIT licensed](LICENSE)

@@ -1004,5 +1064,2 @@

[FL]: https://github.com/fantasyland/fantasy-land
[FL1]: https://github.com/fantasyland/fantasy-land/tree/v1.0.1
[FL2]: https://github.com/fantasyland/fantasy-land/tree/v2.2.0
[FL3]: https://github.com/fantasyland/fantasy-land
[FL:alternative]: https://github.com/fantasyland/fantasy-land#alternative

@@ -1014,4 +1071,7 @@ [FL:functor]: https://github.com/fantasyland/fantasy-land#functor

[FL:bifunctor]: https://github.com/fantasyland/fantasy-land#bifunctor
[FL:chainrec]: https://github.com/fantasyland/fantasy-land#chainrec
[JS:Object.create]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
[JS:Object.assign]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create
[JS:Array.isArray]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
[S]: https://sanctuary.js.org/

@@ -1022,2 +1082,4 @@ [S:Either]: https://sanctuary.js.org/#either-type

[STI]: https://github.com/sanctuary-js/sanctuary-type-identifiers
[Z:Functor]: https://github.com/sanctuary-js/sanctuary-type-classes#Functor

@@ -1033,2 +1095,4 @@ [Z:Bifunctor]: https://github.com/sanctuary-js/sanctuary-type-classes#Bifunctor

[Rollup]: https://rollupjs.org/
[1]: https://github.com/futurize/futurize

@@ -1042,1 +1106,2 @@ [2]: https://drboolean.gitbooks.io/mostly-adequate-guide/content/ch7.html

[8]: http://erikfuente.com/
[9]: http://wearereasonablepeople.nl/
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc