Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

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 0.6.0-beta2 to 0.6.1

277

fluture.js

@@ -23,12 +23,2 @@ /*global define FantasyLand inspectf*/

/////////////
// Helpers //
/////////////
function noop(){}
function fork(m, rej, res){
const clean = m._f(rej, res);
return typeof clean === 'function' ? clean : noop;
}
///////////////////

@@ -54,6 +44,2 @@ // Type checking //

function isBoolean(b){
return typeof b === 'boolean';
}
////////////////////

@@ -104,5 +90,4 @@ // Error handling //

function check$Future(f, b){
if(!isFunction(f)) error$invalidArgument('Future', 0, 'be a function', f);
if(!isBoolean(b)) error$invalidArgument('Future', 0, 'be a boolean', b);
function check$Future(fork){
if(!isFunction(fork)) error$invalidArgument('Future', 0, 'be a function', fork);
}

@@ -150,2 +135,3 @@

//Check resolution value of the Future on which #ap was called.
function check$ap$f(f){

@@ -187,8 +173,8 @@ if(!isFunction(f)) throw new TypeError(

function check$cache$settle(oldState, newState, oldValue, newValue){
if(oldState !== 'pending') throw new Error(
'A cached Future may only resolve or reject once;'
+ ` tried to go into a ${newState} state while already ${oldState}.`
if(oldState > 1) throw new Error(
'Future.cache expects the Future it wraps to only resolve or reject once; '
+ ' a cached Future tried to ' + (newState === 2 ? 'reject' : 'resolve') + ' a second time.'
+ ' Please check your cached Future and make sure it does not call res or rej multiple times'
+ `\n It was ${oldState} with: ${show(oldValue)}`
+ `\n It got ${newState} with: ${show(newValue)}`
+ '\n It was ' + (oldState === 2 ? 'rejected' : 'resolved') + ' with: ' + show(oldValue)
+ '\n It got ' + (newState === 2 ? 'rejected' : 'resolved') + ' with: ' + show(newValue)
);

@@ -229,13 +215,14 @@ }

function FutureClass(f, b){
//Constructor.
function FutureClass(f){
this._f = f;
this._b = b;
}
function Future(f, b){
if(arguments.length < 2) b = true;
check$Future(f, b);
return new FutureClass(f, b);
//A createFuture function which pretends to be Future.
function Future(f){
check$Future(f);
return new FutureClass(f);
}
//The of method.
function Future$of(x){

@@ -249,13 +236,3 @@ return new FutureClass(function Future$of$fork(rej, res){

check$fork(this, rej, res);
let immediate = false, clear;
const autoclear = this._b;
clear = fork(this, function Future$fork$rej(x){
rej(x);
autoclear && clear ? clear() : (immediate = true);
}, function Future$fork$res(x){
res(x);
autoclear && clear ? clear() : (immediate = true);
});
autoclear && immediate && clear();
return clear;
this._f(rej, res);
}

@@ -267,17 +244,8 @@

return new FutureClass(function Future$chain$fork(rej, res){
let cleared = false, clearThat = noop;
const clearThis = fork(_this, function Future$chain$rej(x){
cleared || rej(x);
}, function Future$chain$res(x){
if(cleared) return;
_this._f(rej, function Future$chain$res(x){
const m = f(x);
check$chain$f(m, f, x);
clearThat = fork(m, e => cleared || rej(e), x => cleared || res(x));
m._f(rej, res);
});
return function Future$chain$clear(){
cleared = true;
clearThis();
clearThat();
};
}, this._b);
});
}

@@ -289,17 +257,8 @@

return new FutureClass(function Future$chainRej$fork(rej, res){
let cleared = false, clearThat = noop;
const clearThis = fork(_this, function Future$chainRej$rej(x){
if(cleared) return;
_this._f(function Future$chainRej$rej(x){
const m = f(x);
check$chainRej$f(m, f, x);
clearThat = fork(m, e => cleared || rej(e), x => cleared || res(x));
}, function Future$chainRej$res(x){
cleared || res(x);
});
return function Future$chainRej$clear(){
cleared = true;
clearThis();
clearThat();
};
}, _this._b);
m._f(rej, res);
}, res);
});
}

@@ -311,13 +270,6 @@

return new FutureClass(function Future$map$fork(rej, res){
let cleared = false;
const clear = fork(_this, function Future$map$rej(x){
cleared || rej(x);
}, function Future$map$res(x){
cleared || res(f(x));
_this._f(rej, function Future$map$res(x){
res(f(x));
});
return function Future$map$clear(){
cleared = true;
clear();
};
}, _this._b);
});
}

@@ -329,6 +281,5 @@

return new FutureClass(function Future$ap$fork(g, res){
let _f, _x, ok1, ok2, ko, cleared = false;
const rej = x => cleared || ko || (ko = 1, g(x));
const clearThis = fork(_this, rej, function Future$ap$resThis(f){
if(cleared) return;
let _f, _x, ok1, ok2, ko;
const rej = x => ko || (ko = 1, g(x));
_this._f(rej, function Future$ap$resThis(f){
if(!ok2) return void (ok1 = 1, _f = f);

@@ -338,4 +289,3 @@ check$ap$f(f);

});
const clearThat = fork(m, rej, function Future$ap$resThat(x){
if(cleared) return;
m._f(rej, function Future$ap$resThat(x){
if(!ok1) return void (ok2 = 1, _x = x)

@@ -345,8 +295,3 @@ check$ap$f(_f);

});
return function Future$ap$clear(){
cleared = true;
clearThis();
clearThat();
};
}, _this._b);
});
}

@@ -362,12 +307,7 @@

return new FutureClass(function Future$race$fork(rej, res){
let settled = false, cleared = false;
const once = f => a => cleared || settled || (settled = true, f(a));
const clearThis = fork(_this, once(rej), once(res));
const clearThat = fork(m, once(rej), once(res));
return function Future$race$clear(){
cleared = true;
clearThis();
clearThat();
};
}, _this._b);
let settled = false;
const once = f => a => settled || (settled = true, f(a));
_this._f(once(rej), once(res));
m._f(once(rej), once(res));
});
}

@@ -379,17 +319,12 @@

return new FutureClass(function Future$or$fork(rej, res){
let ok = false, ko = false, val, err, cleared = false;
const clearThis = fork(_this,
() => cleared || ko ? rej(err) : ok ? res(val) : (ko = true),
x => cleared || (ok = true, res(x))
let ok = false, ko = false, val, err;
_this._f(
() => ko ? rej(err) : ok ? res(val) : (ko = true),
x => (ok = true, res(x))
);
const clearThat = fork(m,
e => cleared || ok || (ko ? rej(e) : (err = e, ko = true)),
x => cleared || ok || (ko ? res(x) : (val = x, ok = true))
m._f(
e => ok || (ko ? rej(e) : (err = e, ko = true)),
x => ok || (ko ? res(x) : (val = x, ok = true))
);
return function Future$or$clear(){
cleared = true;
clearThis();
clearThat();
};
}, _this._b);
});
}

@@ -401,13 +336,4 @@

return new FutureClass(function Future$fold$fork(rej, res){
let cleared = false;
const clear = fork(_this, function Future$fold$rej(e){
cleared || res(f(e));
}, function Future$fold$res(x){
cleared || res(g(x));
});
return function Future$fold$clear(){
cleared = true;
clear();
};
}, _this._b);
_this._f(e => res(f(e)), x => res(g(x)));
});
}

@@ -417,3 +343,3 @@

check$value(this, f);
return this.fork(
this._f(
function Future$value$rej(e){

@@ -439,5 +365,5 @@ throw new Error(

const _this = this;
let que = [], value, state = 'idle';
let que = [];
let value, state;
const settleWith = newState => function Future$cache$settle(newValue){
if(state === 'idle') return;
check$cache$settle(state, newState, value, newValue);

@@ -452,19 +378,12 @@ value = newValue; state = newState;

return new FutureClass(function Future$cache$fork(rej, res){
let clear = noop;
switch(state){
case 'pending': que.push({rejected: rej, resolved: res}); break;
case 'rejected': rej(value); break;
case 'resolved': res(value); break;
case 'idle':
state = 'pending';
que.push({rejected: rej, resolved: res});
clear = fork(_this, settleWith('rejected'), settleWith('resolved'));
case 1: que.push({2: rej, 3: res}); break;
case 2: rej(value); break;
case 3: res(value); break;
default:
state = 1;
que.push({2: rej, 3: res});
_this.fork(settleWith(2), settleWith(3));
}
return function Future$cache$clear(){
state = 'idle';
value = undefined;
que = [];
clear();
};
}, false);
});
}

@@ -532,19 +451,39 @@

//chain :: Chain m => (a -> m b) -> m a -> m b
Future.chain = createUnaryDispatcher('chain');
//chainRej :: (a -> Future a c) -> Future a b -> Future a c
Future.chainRej = createUnaryDispatcher('chainRej');
//map :: Functor m => (a -> b) -> m a -> m b
Future.map = createUnaryDispatcher('map');
//ap :: Apply m => m (a -> b) -> m a -> m b
Future.ap = function dispatch$ap(m, a){
if(arguments.length === 1) return a => dispatch$ap(m, a);
if(m && typeof m.ap === 'function') return m.ap(a);
error$invalidArgument('Future.ap', 0, 'have a "ap" method', m);
};
//fork :: (a -> Void) -> (b -> Void) -> Future a b -> Void
Future.fork = createBinaryDispatcher('fork');
//race :: Future a b -> Future a b -> Future a b
Future.race = createUnaryDispatcher('race');
//or :: Future a b -> Future a b -> Future a b
Future.or = createUnaryDispatcher('or');
//fold :: (a -> c) -> (b -> c) -> Future a b -> Future _ c
Future.fold = createBinaryDispatcher('fold');
//value :: (b -> Void) -> Future a b -> Void
Future.value = createUnaryDispatcher('value');
//promise :: Future a b -> Promise b a
Future.promise = createNullaryDispatcher('promise');
//cache :: Future a b -> Future a b
Future.cache = createNullaryDispatcher('cache');
Future.ap = function dispatch$ap(m, a){
if(arguments.length === 1) return a => dispatch$ap(m, a);
if(m && typeof m.ap === 'function') return m.ap(a);
error$invalidArgument('Future.ap', 0, 'have a "ap" method', m);
};
//////////////////

@@ -554,2 +493,3 @@ // Constructors //

//Create a Future which rejects witth the given value.
Future.reject = function Future$reject(x){

@@ -561,2 +501,3 @@ return new FutureClass(function Future$reject$fork(rej){

//Create a Future which resolves after the given time with the given value.
Future.after = function Future$after(n, x){

@@ -566,6 +507,3 @@ if(arguments.length === 1) return x => Future$after(n, x);

return new FutureClass(function Future$after$fork(rej, res){
const id = setTimeout(res, n, x);
return function Future$after$clear(){
clearTimeout(id);
};
setTimeout(res, n, x);
})

@@ -575,17 +513,12 @@ };

Future.cast = function Future$cast(m){
check$cast(m);
if(m instanceof FutureClass){
return m;
}
check$cast(m);
return new FutureClass(function Future$cast$fork(rej, res){
let cleared = false;
m.fork(function Future$cast$rej(x){
cleared || rej(x);
}, function Future$cast$res(x){
cleared || res(x);
});
return () => (cleared = true);
m.fork(rej, res);
});
};
//encase :: (a -> !b | c) -> a -> Future b c
Future.encase = function Future$encase(f, x){

@@ -606,2 +539,4 @@ if(arguments.length === 1) return x => Future$encase(f, x);

//Create a Future which resolves with the return value of the given function,
//or rejects with the exception thrown by the given function.
Future.try = function Future$try(f){

@@ -611,11 +546,11 @@ return Future.encase(f, undefined);

//node :: ((err, a) -> Void) -> Future[Error, a]
Future.node = function Future$node(f){
check$node(f);
return new FutureClass(function Future$node$fork(rej, res){
let cleared = false;
f((a, b) => cleared || (a ? rej(a) : res(b)));
return () => (cleared = true);
f((a, b) => a ? rej(a) : res(b));
});
};
//parallel :: PositiveInteger -> [Future a b] -> Future a [b]
Future.parallel = function Future$parallel(i, ms){

@@ -626,17 +561,11 @@ if(arguments.length === 1) return ms => Future$parallel(i, ms);

return l < 1 ? Future$of([]) : new FutureClass(function Future$parallel$fork(rej, res){
let ko = false, ok = 0, cleared = false;
const clears = [], out = new Array(l);
const next = j => i < l ? run(ms[i], i++) : (j === l && res(out));
const run = (m, j) => {
check$parallel$m(m, j);
clears.push(fork(m,
e => cleared || ko || (rej(e), ko = true),
x => cleared || ko || (out[j] = x, next(++ok))
));
}
ms.slice(0, i).forEach(run);
return function Future$parallel$clear(){
cleared = true;
clears.forEach(f => f());
};
let ko = false;
let ok = 0;
const out = new Array(l);
const next = j => i < l ? fork(ms[i], i++) : (j === l && res(out));
const fork = (m, j) => (check$parallel$m(m, j), m._f(
e => ko || (rej(e), ko = true),
x => ko || (out[j] = x, next(++ok))
));
ms.slice(0, i).forEach(fork);
});

@@ -643,0 +572,0 @@ };

{
"name": "fluture",
"version": "0.6.0-beta2",
"version": "0.6.1",
"description": "A mathematically correct alternative to Promises for asynchronous control flow",

@@ -15,6 +15,5 @@ "main": "fluture.js",

"setup": "npm run post-merge && cp scripts/hooks/* .git/hooks && git config push.followTags true",
"test": "npm run check-version && npm run clean && npm run lint && npm run test:coverage",
"test": "npm run check-version && npm run clean && npm run lint && npm run test:unit",
"test:opt": "node --allow-natives-syntax --trace-opt --trace-deopt --trace-inlining scripts/test-opt",
"test:unit": "node --harmony-destructuring ./node_modules/.bin/_mocha --ui bdd --reporter spec --check-leaks --full-trace",
"test:coverage": "node --harmony-destructuring node_modules/.bin/istanbul cover --report html ./node_modules/.bin/_mocha -- --ui bdd --reporter dot --bail --check-leaks && codecov"
"test:unit": "node --harmony-destructuring node_modules/.bin/istanbul cover --report html ./node_modules/.bin/_mocha -- --ui bdd --reporter spec --check-leaks --full-trace && codecov"
},

@@ -21,0 +20,0 @@ "author": "Aldwin Vlasblom <aldwin.vlasblom@gmail.com> (https://github.com/Avaq)",

@@ -8,3 +8,3 @@ # Fluture

[![Build Status](https://travis-ci.org/Avaq/Fluture.svg?branch=master)](https://travis-ci.org/Avaq/Fluture)
[![Code Coverage](https://codecov.io/github/Avaq/Fluture/coverage.svg?branch=master)](https://codecov.io/github/Avaq/Fluture/fluture.js?branch=master)
[![Code Coverage](https://codecov.io/github/Avaq/Fluture/coverage.svg?branch=develop)](https://codecov.io/github/Avaq/Fluture/fluture.js?branch=develop)

@@ -19,16 +19,3 @@ Futures are containers which represent some eventual value as a result of an

## Table of contents
- [Usage](#usage)
- [Motivation and Features](#motivation-and-features)
- [Documentation](#documentation)
- [Type signatures](#type-signatures)
- [Creation](#creation)
- [Method API](#method-api)
- [Dispatcher API](#dispatcher-api)
- [Cancellation and resource disposal](#cancellation-and-resource-disposal)
- [Futurization](#futurization)
- [Benchmarks](#benchmarks)
- [The name](#the-name)
## Usage

@@ -64,17 +51,11 @@

## Motivation and Features
## Motivation
Existing implementations of Future are a pain to debug. This library was made in
an effort to provide **great error messages** when something goes wrong. Some
other features include:
an effort to provide **great error messages** when something goes wrong. The
library also comes bundled with many **async control utilities**. To prevent
these features from coming at the cost of performance, Fluture was optimized to
operate at **high performance**. For an overview of differences between Fluture
and other Future implementations, look at [this wiki article][15].
* Plenty of async control utilities, like
[`Future.parallel`](#parallel--positiveinteger---future-a-b---future-a-b)
and [`Future#or`](#or--future-a-b--future-a-b---future-a-b).
* [Process cancellation and automatic resource disposal](#cancellation-and-resource-disposal).
* High performance.
For an overview of differences between Fluture and other Future implementations,
have a look at [this wiki article][15].
## Documentation

@@ -98,21 +79,13 @@

### Creation
### Constructors
#### `Future :: ((a -> ()), (b -> ()) -> ?(() -> ())) -> ?Bool -> Future a b`
#### `Future :: ((a -> Void), (b -> Void) -> Void) -> Future a b`
The Future constructor. Creates a new instance of Future. Takes two parameters:
A (monadic) container which represents an eventual value. A lot like Promise but
more principled in that it follows the [Fantasy Land][1] algebraic JavaScript
specification.
* `fork`: A function which takes two callbacks. Both are continuations for an
asynchronous computation. The first is `reject`, commonly abreviated to `rej`.
The second `resolve`, which abreviates to `res`. The `fork` function is
expected to call `rej` once an error occurs, or `res` with the result of the
asynchronous computation. Additionally, another function *may* be returned to
be used for [cancellation or resource disposal](#cancellation-and-resource-disposal).
* `autoclear`: Whether to [automatically dispose of resources](#automatic-resource-disposal)
when a resource disposal function is returned from `fork`. Defaults to true.
It's quite likely you'll never need to override this.
```js
const eventualThing = Future((rej, res) => {
setTimeout(res, 500, 'world');
const eventualThing = Future((reject, resolve) => {
setTimeout(resolve, 500, 'world');
});

@@ -127,7 +100,5 @@

#### `of :: a -> Future _ a`
#### `of :: b -> Future a b`
Creates a Future which immediately resolves with the given value. This function
is compliant with the [Fantasy Land Applicative specification][16] and is
also available on the prototype.
A constructor that creates a Future containing the given value.

@@ -143,10 +114,5 @@ ```js

#### `reject :: a -> Future a _`
Creates a Future which immediately rejects with the given value. Just like `of`
but for the rejection branch.
#### `after :: Number -> b -> Future a b`
Creates a Future which resolves with the given value after n milliseconds.
A constructor that creates a Future containing the given value after n milliseconds.

@@ -180,6 +146,6 @@ ```js

#### `try :: (() -> !a | b) -> Future a b`
#### `try :: (Void -> !a | b) -> Future a b`
Creates a Future which resolves with the result of calling the given function,
or rejects with the error thrown by the given function.
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.

@@ -195,10 +161,9 @@ Sugar for `Future.encase(f, undefined)`.

#### `node :: ((a, b -> ()) -> ()) -> Future a b`
#### `node :: ((a, b -> Void) -> Void) -> Future a b`
Creates a Future which rejects with the first argument given to the function,
or resolves with the second if the first is not present.
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. To permanently turn a function into one that returns
a Future, check out [futurization](#futurization).
a node style callback API.

@@ -255,11 +220,34 @@ ```js

#### `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 eventualPackage = Future.cache(
Future.node(done => {
console.log('Reading some big data');
fs.readFile('package.json', 'utf8', done)
})
);
eventualPackage.fork(console.error, console.log);
//> "Reading some big data"
//> "{...}"
eventualPackage.fork(console.error, console.log);
//> "{...}"
```
### Method API
#### `fork :: Future a b ~> (a -> ()), (b -> ()) -> () -> ()`
#### `fork :: Future a b ~> (a -> Void), (b -> Void) -> Void`
Execute the Future by calling the `fork` function that was passed to it at
[construction](#creation) with the `reject` and `resolve` callbacks. Futures are
*lazy*, which means even if you've `map`ped or `chain`ed over them, they'll do
*nothing* if you don't eventually fork them.
Execute the Future (which up until now was merely a container for its
computation), and get at the result or error.
It is the return from Fantasy Land to the real world. This function best shows
the fundamental difference between Promises and Futures.
```js

@@ -281,8 +269,4 @@ Future.of('world').fork(

Transforms the resolution value inside the Future, and returns a new Future with
the transformed value. This is like doing `promise.then(x => x + 1)`, except
that it's lazy, so the transformation will not be applied before the Future is
forked. The transformation is only applied to the resolution branch. So if the
Future is rejected, the transformation is ignored. To learn more about the exact
behaviour of `map`, check out its [spec][12].
Map over the value inside the Future. If the Future is rejected, mapping is not
performed.

@@ -298,7 +282,4 @@ ```js

Allows the creation of a new Future based on the resolution value. This is like
doing `promise.then(x => Promise.resolve(x + 1))`, except that it's lazy, so the
new Future will not be created until the other one is forked. The function is
only ever applied to the resolution value, so is ignored when the Future was
rejected. To learn more about the exact behaviour of `chain`, check out its [spec][13].
FlatMap over the value inside the Future. If the Future is rejected, chaining is
not performed.

@@ -314,4 +295,4 @@ ```js

Chain over the **rejection** reason of the Future. This is like `chain`, but for
the rejection branch.
FlatMap over the **rejection** value inside the Future. If the Future is
resolved, chaining is not performed.

@@ -329,7 +310,4 @@ ```js

Apply the resolution value, which is expected to be a function (as in
`Future.of(a_function)`), to the resolution value in the given Future. Both
Futures involved will run in parallel, and if one rejects the resulting Future
will also be rejected. To learn more about the exact behaviour of `ap`, check
out its [spec][14].
Apply the value in the Future to the value in the given Future. If the Future is
rejected, applying is not performed.

@@ -399,32 +377,4 @@ ```js

#### `cache :: Future a b ~> Future a b`
#### `value :: Future a b ~> (b -> Void) -> Void`
Returns a cached version of the Future so that whenever it's forked, it can load
the value from cache rather than reexecuting the chain. This means you can use
the same Future in multiple `chain`s, without having to worry that it's going
to re-execute the computation every time.
Please note that cached Futures, and Futures derived from them do not
automatically [dispose of resources](#automatic-resource-disposal). When the
cached Future is [cancelled or disposed manually](#manual-resource-disposal-and-cancellation),
it will clear its internal cache. The next time it's forked *after* that, it
must re-execute the underlying Future to populate its cache again.
```js
const eventualPackage = Future.node(done => {
console.log('Reading some big data');
fs.readFile('package.json', 'utf8', done)
})
.cache();
eventualPackage.fork(console.error, console.log);
//> "Reading some big data"
//> "{...}"
eventualPackage.fork(console.error, console.log);
//> "{...}"
```
#### `value :: Future a b ~> (b -> ()) -> () -> ()`
Extracts the value from a resolved Future by forking it. Only use this function

@@ -456,3 +406,3 @@ if you are sure the Future is going to be resolved, for example; after using

#### `fork :: (a -> ()) -> (b -> ()) -> Future a b -> () -> ()`
#### `fork :: (a -> Void) -> (b -> Void) -> Future a b -> Void`

@@ -520,93 +470,6 @@ Dispatches the first and second arguments to the `fork` method of the third argument.

#### `cache :: Future a b -> Future a b`
#### `value :: (b -> Void) -> Future a b -> Void`
Dispatches to the `cache` method.
```js
const cachedConnection = Future.cache(mysqlConnect());
```
#### `value :: (b -> ()) -> Future a b -> () -> ()`
Dispatches the first argument to the `value` method of the second argument.
#### `promise :: Future a b -> Promise b a`
Dispatches to the `promise` method.
```js
Future.promise(Future.after(300, 'Hello')).then(console.log);
//> "Hello"
```
### Cancellation and resource disposal
#### Automatic resource disposal
When a Future is created, it is given the `fork` function. This `fork` function
sometimes creates resources, like `setTimeout`s in the event loop or database
connections. In order to deal with the disposal of these resources, one may
*return* a function from `fork`, which will be automatically called after the
Future has forked. This function is expected to be idempotent.
It's the responsibility of this `fork` function to prevent `rej` or `res` from
being called after its returned disposal function has been called. All of the
functions in Fluture play by these rules.
```js
const createDatabaseConnection = settings => Future((rej, res) => {
const conn = mysql.connect(settings, res);
return () => conn.hasEnded || conn.end();
});
createDatabaseConnection()
.chain(conn => conn.query('SELECT 1 + 1 AS two'))
//When we `fork`, all of the resource disposers will be automatically called.
.fork(console.error, console.log);
```
If you don't want a particular Future to automatically dispose of its resources,
you can construct it with `false` passed as its second argument:
```js
Future(
rej => {
const id = setTimeout(rej, 2000, 'timed out')
return () => clearTimeout(id);
},
false //<---
)
```
This Future, and any Future's derived from it through `map`, `chain`, etc. will
no longer automatically dispose of their resources after being forked. This
allows resources to only be disposed manually.
#### Manual resource disposal and cancellation
Both `.fork()` and `.value()` return the disposal function and you can call it
at any time to manually dispose of resources.
Besides resource disposal, this function can also be used to cancel running
Futures. When called prematurely it will dispose the resources and cause the
whole pipeline to come to a halt:
```js
const loadPage = url => Future((rej, res) => {
const req = new XMLHttpRequest();
req.addEventListener('load', res);
req.addEventListener('error', rej);
req.open('GET', url);
req.send();
return () => (req.readyState < 4) && req.abort();
});
const cancel = loadPage('https://github.com').fork(onFailure, onSuccess);
//Cancel the Future immediately. Nothing will happen; `onFailure` nor
//`onSuccess` will ever be called anymore because `cancel` called `req.abort()`.
cancel();
```
### Futurization

@@ -662,2 +525,1 @@

[15]: https://github.com/Avaq/Fluture/wiki/Comparison-of-Future-Implementations
[16]: https://github.com/fantasyland/fantasy-land#applicative
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