Comparing version 11.0.1 to 12.0.0-beta.0
209
index.d.ts
@@ -41,17 +41,7 @@ declare module 'fluture' { | ||
/** The function is waiting for two more arguments. */ | ||
export interface AwaitingTwo<A, B, R> { | ||
(a: A, b: B): R | ||
(a: A): (b: B) => R | ||
} | ||
/** The function is waiting for three more arguments. */ | ||
export interface AwaitingThree<A, B, C, R> { | ||
(a: A, b: B, c: C): R | ||
(a: A, b: B): (c: C) => R | ||
(a: A): AwaitingTwo<B, C, R> | ||
} | ||
export interface ConcurrentFutureInstance<L, R> { | ||
sequential: FutureInstance<L, R> | ||
'fantasy-land/ap'<A, B>(this: ConcurrentFutureInstance<L, (value: A) => B>, right: ConcurrentFutureInstance<L, A>): ConcurrentFutureInstance<L, B> | ||
'fantasy-land/map'<RB>(mapper: (value: R) => RB): ConcurrentFutureInstance<L, RB> | ||
'fantasy-land/alt'(right: ConcurrentFutureInstance<L, R>): ConcurrentFutureInstance<L, R> | ||
} | ||
@@ -61,31 +51,7 @@ | ||
/** Apply a function to this Future. See https://github.com/fluture-js/Fluture#pipe */ | ||
pipe<T>(fn: (future: FutureInstance<L, R>) => T): T | ||
/** Logical and for Futures. See https://github.com/fluture-js/Fluture#and */ | ||
and<RB>(right: FutureInstance<L, RB>): FutureInstance<L, RB> | ||
/** Logical or for Futures. See https://github.com/fluture-js/Fluture#alt */ | ||
alt(right: FutureInstance<L, R>): FutureInstance<L, R> | ||
/** Apply the function in this Future to the value in another. See https://github.com/fluture-js/Fluture#ap */ | ||
ap<A, B>(this: FutureInstance<L, (value: A) => B>, right: FutureInstance<L, A>): FutureInstance<L, B> | ||
/** Map over both branches of the Future at once. See https://github.com/fluture-js/Fluture#bimap */ | ||
bimap<LB, RB>(lmapper: (reason: L) => LB, rmapper: (value: R) => RB): FutureInstance<LB, RB> | ||
/** Wait for this Future and the given one in parallel. See https://github.com/fluture-js/Fluture#both */ | ||
both<RB>(right: FutureInstance<L, RB>): FutureInstance<L, [R, RB]> | ||
/** Use the resolution value in this Future to create the next Future. See https://github.com/fluture-js/Fluture#chain */ | ||
chain<RB>(mapper: (value: R) => FutureInstance<L, RB>): FutureInstance<L, RB> | ||
/** Use the rejection reason in this Future to create the next Future. See https://github.com/fluture-js/Fluture#chainrej */ | ||
chainRej<LB>(mapper: (reason: L) => FutureInstance<LB, R>): FutureInstance<LB, R> | ||
/** The Future constructor */ | ||
constructor: FutureTypeRep | ||
/** Fork the Future into a Node-style callback. See https://github.com/fluture-js/Fluture#done */ | ||
done(callback: Nodeback<L, R>): Cancel | ||
/** Apply a function to this Future. See https://github.com/fluture-js/Fluture#pipe */ | ||
pipe<T>(fn: (future: FutureInstance<L, R>) => T): T | ||
@@ -98,75 +64,38 @@ /** Attempt to extract the rejection reason. See https://github.com/fluture-js/Fluture#extractleft */ | ||
/** Set up a cleanup Future to run after this one is done. See https://github.com/fluture-js/Fluture#finally */ | ||
finally(cleanup: FutureInstance<L, any>): FutureInstance<L, R> | ||
'fantasy-land/ap'<A, B>(this: FutureInstance<L, (value: A) => B>, right: FutureInstance<L, A>): FutureInstance<L, B> | ||
'fantasy-land/map'<RB>(mapper: (value: R) => RB): FutureInstance<L, RB> | ||
'fantasy-land/alt'(right: FutureInstance<L, R>): FutureInstance<L, R> | ||
'fantasy-land/bimap'<LB, RB>(lmapper: (reason: L) => LB, rmapper: (value: R) => RB): FutureInstance<LB, RB> | ||
'fantasy-land/chain'<RB>(mapper: (value: R) => FutureInstance<L, RB>): FutureInstance<L, RB> | ||
/** Fold both branches into the resolution branch. See https://github.com/fluture-js/Fluture#fold */ | ||
fold<L, RB>(lmapper: (reason: L) => RB, rmapper: (value: R) => RB): FutureInstance<L, RB> | ||
/** Fork the Future into the two given continuations. See https://github.com/fluture-js/Fluture#fork */ | ||
fork(reject: RejectFunction<L>, resolve: ResolveFunction<R>): Cancel | ||
/** Fork with exception recovery. See https://github.com/fluture-js/Fluture#forkCatch */ | ||
forkCatch(recover: RecoverFunction, reject: RejectFunction<L>, resolve: ResolveFunction<R>): Cancel | ||
/** Set up a cleanup Future to run after this one is done. See https://github.com/fluture-js/Fluture#finally */ | ||
lastly(cleanup: FutureInstance<L, any>): FutureInstance<L, R> | ||
/** Map over the resolution value in this Future. See https://github.com/fluture-js/Fluture#map */ | ||
map<RB>(mapper: (value: R) => RB): FutureInstance<L, RB> | ||
/** Map over the rejection reason in this Future. See https://github.com/fluture-js/Fluture#maprej */ | ||
mapRej<LB>(mapper: (reason: L) => LB): FutureInstance<LB, R> | ||
/** Logical or for Futures. See https://github.com/fluture-js/Fluture#alt */ | ||
or(right: FutureInstance<L, R>): FutureInstance<L, R> | ||
/** Fork the Future into a Promise. See https://github.com/fluture-js/Fluture#promise */ | ||
promise(): Promise<R> | ||
/** Race this Future against another one. See https://github.com/fluture-js/Fluture#race */ | ||
race(right: FutureInstance<L, R>): FutureInstance<L, R> | ||
/** Swap the rejection reason and the resolotion value. See https://github.com/fluture-js/Fluture#swap */ | ||
swap(): FutureInstance<R, L> | ||
/** Fork this Future into the given continuation. See https://github.com/fluture-js/Fluture#value */ | ||
value(this: FutureInstance<never, R>, resolve: ResolveFunction<R>): Cancel | ||
} | ||
/** Creates a Future which resolves after the given duration with the given value. See https://github.com/fluture-js/Fluture#after */ | ||
export function after<L, R>(duration: number, value: R): FutureInstance<L, R> | ||
export function after<L, R>(duration: number): (value: R) => FutureInstance<L, R> | ||
/** Logical and for Futures. See https://github.com/fluture-js/Fluture#and */ | ||
export function and<L, R>(left: FutureInstance<L, any>, right: FutureInstance<L, R>): FutureInstance<L, R> | ||
export function and<L, R>(left: FutureInstance<L, any>): (right: FutureInstance<L, R>) => FutureInstance<L, R> | ||
export function and<L, R>(left: FutureInstance<L, R>): (right: FutureInstance<L, any>) => FutureInstance<L, R> | ||
/** Logical or for Futures. See https://github.com/fluture-js/Fluture#alt */ | ||
export function alt<L, R>(left: FutureInstance<L, R>, right: FutureInstance<L, R>): FutureInstance<L, R> | ||
export function alt<L, R>(left: FutureInstance<L, R>): (right: FutureInstance<L, R>) => FutureInstance<L, R> | ||
/** Race two ConcurrentFutures. See https://github.com/fluture-js/Fluture#alt */ | ||
export function alt<L, R>(left: ConcurrentFutureInstance<L, R>, right: ConcurrentFutureInstance<L, R>): ConcurrentFutureInstance<L, R> | ||
export function alt<L, R>(left: ConcurrentFutureInstance<L, R>): (right: ConcurrentFutureInstance<L, R>) => ConcurrentFutureInstance<L, R> | ||
/** Apply the function in the left Future to the value in the right Future. See https://github.com/fluture-js/Fluture#ap */ | ||
export function ap<L, RA, RB>(apply: FutureInstance<L, (value: RA) => RB>, value: FutureInstance<L, RA>): FutureInstance<L, RB> | ||
export function ap<L, RA, RB>(apply: FutureInstance<L, (value: RA) => RB>): (value: FutureInstance<L, RA>) => FutureInstance<L, RB> | ||
export function ap<L, RA, RB>(value: FutureInstance<L, RA>): (apply: FutureInstance<L, (value: RA) => RB>) => FutureInstance<L, RB> | ||
/** Apply the function in the left ConcurrentFuture to the value in the right ConcurrentFuture. See https://github.com/fluture-js/Fluture#ap */ | ||
export function ap<L, RA, RB>(apply: ConcurrentFutureInstance<L, (value: RA) => RB>, value: ConcurrentFutureInstance<L, RA>): ConcurrentFutureInstance<L, RB> | ||
export function ap<L, RA, RB>(apply: ConcurrentFutureInstance<L, (value: RA) => RB>): (value: ConcurrentFutureInstance<L, RA>) => ConcurrentFutureInstance<L, RB> | ||
export function ap<L, RA, RB>(value: ConcurrentFutureInstance<L, RA>): (apply: ConcurrentFutureInstance<L, (value: RA) => RB>) => ConcurrentFutureInstance<L, RB> | ||
/** Create a Future which resolves with the return value of the given function, or rejects with the error it throws. See https://github.com/fluture-js/Fluture#try */ | ||
/** Create a Future which resolves with the return value of the given function, or rejects with the error it throws. See https://github.com/fluture-js/Fluture#attempt */ | ||
export function attempt<L, R>(fn: () => R): FutureInstance<L, R> | ||
/** Convert a Promise-returning function to a Future. See https://github.com/fluture-js/Fluture#attemptP */ | ||
export function attemptP<L, R>(fn: () => Promise<R>): FutureInstance<L, R> | ||
/** Map over both branched of the given Bifunctor at once. See https://github.com/fluture-js/Fluture#bimap */ | ||
export function bimap<LA, LB, RA, RB>(lmapper: (reason: LA) => LB, rmapper: (value: RA) => RB, source: FutureInstance<LA, RA>): FutureInstance<LB, RB> | ||
export function bimap<LA, LB, RA, RB>(lmapper: (reason: LA) => LB, rmapper: (value: RA) => RB): (source: FutureInstance<LA, RA>) => FutureInstance<LB, RB> | ||
export function bimap<LA, LB, RA, RB>(lmapper: (reason: LA) => LB): (rmapper: (value: RA) => RB, source: FutureInstance<LA, RA>) => FutureInstance<LB, RB> | ||
export function bimap<LA, LB, RA, RB>(lmapper: (reason: LA) => LB): (rmapper: (value: RA) => RB) => (source: FutureInstance<LA, RA>) => FutureInstance<LB, RB> | ||
/** Wait for both Futures to resolve in parallel. See https://github.com/fluture-js/Fluture#both */ | ||
export function both<L, A, B>(left: FutureInstance<L, A>, right: FutureInstance<L, B>): FutureInstance<L, [A, B]> | ||
export function both<L, A, B>(left: FutureInstance<L, A>): (right: FutureInstance<L, B>) => FutureInstance<L, [A, B]> | ||
@@ -178,58 +107,16 @@ | ||
/** Create a Future using the resolution value of the given Future. See https://github.com/fluture-js/Fluture#chain */ | ||
export function chain<L, RA, RB>(mapper: (value: RA) => FutureInstance<L, RB>, source: FutureInstance<L, RA>): FutureInstance<L, RB> | ||
export function chain<L, RA, RB>(mapper: (value: RA) => FutureInstance<L, RB>): (source: FutureInstance<L, RA>) => FutureInstance<L, RB> | ||
/** Create a Future using the rejection reason of the given Future. See https://github.com/fluture-js/Fluture#chain */ | ||
export function chainRej<LA, LB, R>(mapper: (reason: LA) => FutureInstance<LB, R>, source: FutureInstance<LA, R>): FutureInstance<LB, R> | ||
export function chainRej<LA, LB, R>(mapper: (reason: LA) => FutureInstance<LB, R>): (source: FutureInstance<LA, R>) => FutureInstance<LB, R> | ||
/** Fork the given Future into a Node-style callback. See https://github.com/fluture-js/Fluture#done */ | ||
export function done<L, R>(callback: Nodeback<L, R>, source: FutureInstance<L, R>): Cancel | ||
export function done<L, R>(callback: Nodeback<L, R>): (source: FutureInstance<L, R>) => Cancel | ||
/** Encase the given function such that it returns a Future of its return value. See https://github.com/fluture-js/Fluture#encase */ | ||
export function encase<L, R, A>(fn: (a: A) => R, a: A): FutureInstance<L, R> | ||
export function encase<L, R, A>(fn: (a: A) => R): (a: A) => FutureInstance<L, R> | ||
/** Encase the given function such that it returns a Future of its return value. See https://github.com/fluture-js/Fluture#encase */ | ||
export function encase2<L, R, A, B>(fn: (a: A, b: B) => R, a: A, b: B): FutureInstance<L, R> | ||
export function encase2<L, R, A, B>(fn: (a: A, b: B) => R, a: A): (b: B) => FutureInstance<L, R> | ||
export function encase2<L, R, A, B>(fn: (a: A, b: B) => R): AwaitingTwo<A, B, FutureInstance<L, R>> | ||
/** Encase the given function such that it returns a Future of its return value. See https://github.com/fluture-js/Fluture#encase */ | ||
export function encase3<L, R, A, B, C>(fn: (a: A, b: B, c: C) => R, a: A, b: B, c: C): FutureInstance<L, R> | ||
export function encase3<L, R, A, B, C>(fn: (a: A, b: B, c: C) => R, a: A, b: B): (c: C) => FutureInstance<L, R> | ||
export function encase3<L, R, A, B, C>(fn: (a: A, b: B, c: C) => R, a: A): AwaitingTwo<B, C, FutureInstance<L, R>> | ||
export function encase3<L, R, A, B, C>(fn: (a: A, b: B, c: C) => R): AwaitingThree<A, B, C, FutureInstance<L, R>> | ||
/** Encase the given Node-style function such that it returns a Future of its result. See https://github.com/fluture-js/Fluture#encasen */ | ||
export function encaseN<L, R, A>(fn: (a: A, callback: Nodeback<L, R>) => void, a: A): FutureInstance<L, R> | ||
export function encaseN<L, R, A>(fn: (a: A, callback: Nodeback<L, R>) => void): (a: A) => FutureInstance<L, R> | ||
/** Encase the given Node-style function such that it returns a Future of its result. See https://github.com/fluture-js/Fluture#encasen */ | ||
export function encaseN2<L, R, A, B>(fn: (a: A, b: B, callback: Nodeback<L, R>) => void, a: A, b: B): FutureInstance<L, R> | ||
export function encaseN2<L, R, A, B>(fn: (a: A, b: B, callback: Nodeback<L, R>) => void, a: A): (b: B) => FutureInstance<L, R> | ||
export function encaseN2<L, R, A, B>(fn: (a: A, b: B, callback: Nodeback<L, R>) => void): AwaitingTwo<A, B, FutureInstance<L, R>> | ||
/** Encase the given Node-style function such that it returns a Future of its result. See https://github.com/fluture-js/Fluture#encasen */ | ||
export function encaseN3<L, R, A, B, C>(fn: (a: A, b: B, c: C, callback: Nodeback<L, R>) => void, a: A, b: B, c: C): FutureInstance<L, R> | ||
export function encaseN3<L, R, A, B, C>(fn: (a: A, b: B, c: C, callback: Nodeback<L, R>) => void, a: A, b: B): (c: C) => FutureInstance<L, R> | ||
export function encaseN3<L, R, A, B, C>(fn: (a: A, b: B, c: C, callback: Nodeback<L, R>) => void, a: A): AwaitingTwo<B, C, FutureInstance<L, R>> | ||
export function encaseN3<L, R, A, B, C>(fn: (a: A, b: B, c: C, callback: Nodeback<L, R>) => void): AwaitingThree<A, B, C, FutureInstance<L, R>> | ||
/** Encase the given Promise-returning function such that it returns a Future of its resolution value. See https://github.com/fluture-js/Fluture#encasep */ | ||
export function encaseP<L, R, A>(fn: (a: A) => Promise<R>, a: A): FutureInstance<L, R> | ||
export function encaseP<L, R, A>(fn: (a: A) => Promise<R>): (a: A) => FutureInstance<L, R> | ||
/** Encase the given Promise-returning function such that it returns a Future of its resolution value. See https://github.com/fluture-js/Fluture#encasep */ | ||
export function encaseP2<L, R, A, B>(fn: (a: A, b: B) => Promise<R>, a: A, b: B): FutureInstance<L, R> | ||
export function encaseP2<L, R, A, B>(fn: (a: A, b: B) => Promise<R>, a: A): (b: B) => FutureInstance<L, R> | ||
export function encaseP2<L, R, A, B>(fn: (a: A, b: B) => Promise<R>): AwaitingTwo<A, B, FutureInstance<L, R>> | ||
/** Encase the given Promise-returning function such that it returns a Future of its resolution value. See https://github.com/fluture-js/Fluture#encasep */ | ||
export function encaseP3<L, R, A, B, C>(fn: (a: A, b: B, c: C) => Promise<R>, a: A, b: B, c: C): FutureInstance<L, R> | ||
export function encaseP3<L, R, A, B, C>(fn: (a: A, b: B, c: C) => Promise<R>, a: A, b: B): (c: C) => FutureInstance<L, R> | ||
export function encaseP3<L, R, A, B, C>(fn: (a: A, b: B, c: C) => Promise<R>, a: A): AwaitingTwo<B, C, FutureInstance<L, R>> | ||
export function encaseP3<L, R, A, B, C>(fn: (a: A, b: B, c: C) => Promise<R>): AwaitingThree<A, B, C, FutureInstance<L, R>> | ||
/** Attempt to extract the rejection reason. See https://github.com/fluture-js/Fluture#extractleft */ | ||
@@ -242,16 +129,9 @@ export function extractLeft<L, R>(source: FutureInstance<L, R>): Array<L> | ||
/** Fold both branches into the resolution branch. See https://github.com/fluture-js/Fluture#fold */ | ||
export function fold<LA, RA, LB, RB>(lmapper: (left: LA) => RA, rmapper: (right: RA) => RB, source: FutureInstance<LA, RA>): FutureInstance<LB, RB> | ||
export function fold<LA, RA, LB, RB>(lmapper: (left: LA) => RA, rmapper: (right: RA) => RB): (source: FutureInstance<LA, RA>) => FutureInstance<LB, RB> | ||
export function fold<LA, RA, LB, RB>(lmapper: (left: LA) => RA): AwaitingTwo<(right: RA) => RB, FutureInstance<LA, RA>, FutureInstance<LB, RB>> | ||
export function fold<LA, RA, LB, RB>(lmapper: (left: LA) => RA): (rmapper: (right: RA) => RB) => (source: FutureInstance<LA, RA>) => FutureInstance<LB, RB> | ||
/** Fork the given Future into the given continuations. See https://github.com/fluture-js/Fluture#fork */ | ||
export function fork<L, R>(reject: RejectFunction<L>, resolve: ResolveFunction<R>, source: FutureInstance<L, R>): Cancel | ||
export function fork<L, R>(reject: RejectFunction<L>, resolve: ResolveFunction<R>): (source: FutureInstance<L, R>) => Cancel | ||
export function fork<L, R>(reject: RejectFunction<L>): AwaitingTwo<ResolveFunction<R>, FutureInstance<L, R>, Cancel> | ||
export function fork<L, R>(reject: RejectFunction<L>): (resolve: ResolveFunction<R>) => (source: FutureInstance<L, R>) => Cancel | ||
/** Fork with exception recovery. See https://github.com/fluture-js/Fluture#forkCatch */ | ||
export function forkCatch<L, R>(recover: RecoverFunction, reject: RejectFunction<L>, resolve: ResolveFunction<R>, source: FutureInstance<L, R>): Cancel | ||
export function forkCatch<L, R>(recover: RecoverFunction, reject: RejectFunction<L>, resolve: ResolveFunction<R>): (source: FutureInstance<L, R>) => Cancel | ||
export function forkCatch<L, R>(recover: RecoverFunction, reject: RejectFunction<L>): AwaitingTwo<ResolveFunction<R>, FutureInstance<L, R>, Cancel> | ||
export function forkCatch<L, R>(recover: RecoverFunction): AwaitingThree<RejectFunction<L>, ResolveFunction<R>, FutureInstance<L, R>, Cancel> | ||
export function forkCatch<L, R>(recover: RecoverFunction): (reject: RejectFunction<L>) => (resolve: ResolveFunction<R>) => (source: FutureInstance<L, R>) => Cancel | ||
@@ -262,5 +142,3 @@ /** Build a coroutine using Futures. See https://github.com/fluture-js/Fluture#go */ | ||
/** Manage resources before and after the computation that needs them. See https://github.com/fluture-js/Fluture#hook */ | ||
export function hook<L, H, R>(acquire: FutureInstance<L, H>, dispose: (handle: H) => FutureInstance<any, any>, consume: (handle: H) => FutureInstance<L, R>): FutureInstance<L, R> | ||
export function hook<L, H, R>(acquire: FutureInstance<L, H>, dispose: (handle: H) => FutureInstance<any, any>): (consume: (handle: H) => FutureInstance<L, R>) => FutureInstance<L, R> | ||
export function hook<L, H, R>(acquire: FutureInstance<L, H>): AwaitingTwo<(handle: H) => FutureInstance<any, any>, (handle: H) => FutureInstance<L, R>, FutureInstance<L, R>> | ||
export function hook<L, H, R>(acquire: FutureInstance<L, H>): (dispose: (handle: H) => FutureInstance<any, any>) => (consume: (handle: H) => FutureInstance<L, R>) => FutureInstance<L, R> | ||
@@ -274,15 +152,11 @@ /** Returns true for Futures. See https://github.com/fluture-js/Fluture#isfuture */ | ||
/** Set up a cleanup Future to run after the given action has settled. See https://github.com/fluture-js/Fluture#lastly */ | ||
export function lastly<L, R>(cleanup: FutureInstance<L, any>, action: FutureInstance<L, R>): FutureInstance<L, R> | ||
export function lastly<L, R>(cleanup: FutureInstance<L, any>): (action: FutureInstance<L, R>) => FutureInstance<L, R> | ||
/** Map over the resolution value of the given Future. See https://github.com/fluture-js/Fluture#map */ | ||
export function map<L, RA, RB>(mapper: (value: RA) => RB, source: FutureInstance<L, RA>): FutureInstance<L, RB> | ||
export function map<L, RA, RB>(mapper: (value: RA) => RB): (source: FutureInstance<L, RA>) => FutureInstance<L, RB> | ||
/** Map over the resolution value of the given ConcurrentFuture. See https://github.com/fluture-js/Fluture#map */ | ||
export function map<L, RA, RB>(mapper: (value: RA) => RB, source: ConcurrentFutureInstance<L, RA>): ConcurrentFutureInstance<L, RB> | ||
export function map<L, RA, RB>(mapper: (value: RA) => RB): (source: ConcurrentFutureInstance<L, RA>) => ConcurrentFutureInstance<L, RB> | ||
/** Map over the rejection reason of the given Future. See https://github.com/fluture-js/Fluture#maprej */ | ||
export function mapRej<LA, LB, R>(mapper: (reason: LA) => LB, source: FutureInstance<LA, R>): FutureInstance<LB, R> | ||
export function mapRej<LA, LB, R>(mapper: (reason: LA) => LB): (source: FutureInstance<LA, R>) => FutureInstance<LB, R> | ||
@@ -297,13 +171,5 @@ | ||
/** Create a Future with the given resolution value. See https://github.com/fluture-js/Fluture#of */ | ||
export function of<L, R>(value: R): FutureInstance<L, R> | ||
/** Create a Future with the given resolution value. See https://github.com/fluture-js/Fluture#of */ | ||
export function resolve<L, R>(value: R): FutureInstance<L, R> | ||
/** Logical or for Futures. See https://github.com/fluture-js/Fluture#alt */ | ||
export function or<L, R>(left: FutureInstance<L, R>, right: FutureInstance<L, R>): FutureInstance<L, R> | ||
export function or<L, R>(left: FutureInstance<L, R>): (right: FutureInstance<L, R>) => FutureInstance<L, R> | ||
/** Run an Array of Futures in parallel, under the given concurrency limit. See https://github.com/fluture-js/Fluture#parallel */ | ||
export function parallel<L, R>(concurrency: number, futures: Array<FutureInstance<L, R>>): FutureInstance<L, Array<R>> | ||
export function parallel<L, R>(concurrency: number): (futures: Array<FutureInstance<L, R>>) => FutureInstance<L, Array<R>> | ||
@@ -315,3 +181,2 @@ | ||
/** Race two Futures against one another. See https://github.com/fluture-js/Fluture#race */ | ||
export function race<L, R>(left: FutureInstance<L, R>, right: FutureInstance<L, R>): FutureInstance<L, R> | ||
export function race<L, R>(left: FutureInstance<L, R>): (right: FutureInstance<L, R>) => FutureInstance<L, R> | ||
@@ -323,3 +188,2 @@ | ||
/** Creates a Future which rejects after the given duration with the given reason. See https://github.com/fluture-js/Fluture#rejectafter */ | ||
export function rejectAfter<L, R>(duration: number, reason: L): FutureInstance<L, R> | ||
export function rejectAfter<L, R>(duration: number): (reason: L) => FutureInstance<L, R> | ||
@@ -333,7 +197,3 @@ | ||
/** Convert a Promise-returning function to a Future. See https://github.com/fluture-js/Fluture#tryP */ | ||
export function tryP<L, R>(fn: () => Promise<R>): FutureInstance<L, R> | ||
/** Fork the Future into the given continuation. See https://github.com/fluture-js/Fluture#value */ | ||
export function value<R>(resolve: ResolveFunction<R>, source: FutureInstance<never, R>): Cancel | ||
export function value<R>(resolve: ResolveFunction<R>): (source: FutureInstance<never, R>) => Cancel | ||
@@ -352,20 +212,5 @@ | ||
/** Create a Future from a possibly cancellable computation. See https://github.com/fluture-js/Fluture#future */ | ||
new <L, R>(computation: ( | ||
reject: RejectFunction<L>, | ||
resolve: ResolveFunction<R> | ||
) => Cancel | void): FutureInstance<L, R> | ||
'fantasy-land/chainRec'<L, I, R>(iterator: (next: (value: I) => Next<I>, done: (value: R) => Done<R>, value: I) => FutureInstance<L, Next<I> | Done<R>>, initial: I): FutureInstance<L, R> | ||
'fantasy-land/of': typeof resolve | ||
/** Implementation of Fantasy Land ChainRec. */ | ||
chainRec<L, I, R>(iterator: (next: (value: I) => Next<I>, done: (value: R) => Done<R>, value: I) => FutureInstance<L, Next<I> | Done<R>>, initial: I): FutureInstance<L, R> | ||
ap: typeof ap | ||
alt: typeof alt | ||
bimap: typeof bimap | ||
chain: typeof chain | ||
map: typeof map | ||
of: typeof resolve | ||
resolve: typeof resolve | ||
reject: typeof reject | ||
'@@type': string | ||
@@ -383,9 +228,5 @@ | ||
of<L, R>(value: R): ConcurrentFutureInstance<L, R> | ||
zero<L, R>(): ConcurrentFutureInstance<L, R> | ||
'fantasy-land/of'<L, R>(value: R): ConcurrentFutureInstance<L, R> | ||
'fantasy-land/zero'<L, R>(): ConcurrentFutureInstance<L, R> | ||
ap: typeof ap | ||
map: typeof map | ||
alt: typeof alt | ||
'@@type': string | ||
@@ -392,0 +233,0 @@ |
{ | ||
"name": "fluture", | ||
"version": "11.0.1", | ||
"version": "12.0.0-beta.0", | ||
"description": "FantasyLand compliant (monadic) alternative to Promises", | ||
@@ -20,12 +20,13 @@ "main": "index", | ||
"clean": "rimraf npm-debug.log coverage index.js .esm-cache .nyc_output node_modules/.cache", | ||
"lint": "eslint --ext mjs src test index.mjs index.cjs.mjs README.md", | ||
"lint": "eslint --ext mjs src test index.mjs index.cjs.mjs", | ||
"lint:readme": "remark --no-stdout --frail -u remark-validate-links README.md", | ||
"release": "xyz --edit --repo git@github.com:fluture-js/Fluture.git --tag 'X.Y.Z' --script scripts/distribute --increment", | ||
"test": "npm run lint && npm run lint:readme && npm run test:unit && npm run test:prop && npm run test:types && npm run test:build", | ||
"test": "npm run lint && npm run lint:readme && npm run test:unit && npm run test:prop && npm run test:integration && npm run test:types && npm run test:build", | ||
"test:integration": "npm run clean && mocha --require esm --ui bdd --reporter list --full-trace --check-leaks --bail test/integration.js", | ||
"test:unit": "npm run clean && mocha --require esm --ui bdd --reporter list --full-trace --check-leaks --bail test/unit.js", | ||
"test:prop": "npm run clean && mocha --require esm --ui bdd --reporter list --full-trace --bail test/prop.js", | ||
"test:build": "npm run clean && npm run build && es-check es5 index.js && mocha --require esm --ui bdd --reporter dot --bail test/build.js", | ||
"test:coverage": "npm run clean && nyc --extension .mjs --include src mocha --require esm --ui bdd --reporter dot test/unit.js test/prop.js || true", | ||
"coverage:upload": "nyc report --reporter=text-lcov > coverage.lcov && codecov", | ||
"coverage:report": "nyc report --reporter=html", | ||
"test:coverage": "npm run clean && nyc --extension .mjs --include src mocha --require esm --ui bdd --reporter dot test/unit.js test/prop.js test/integration.js || true", | ||
"coverage:upload": "nyc report --exclude-after-remap=false --reporter=text-lcov > coverage.lcov && codecov", | ||
"coverage:report": "nyc report --exclude-after-remap=false --reporter=html", | ||
"test:types": "tsc --lib es6 index.d.ts" | ||
@@ -72,9 +73,7 @@ }, | ||
"eslint-config-warp": "^3.0.0", | ||
"eslint-plugin-markdown": "^1.0.0-beta.7", | ||
"esm": "^3.0.81", | ||
"fantasy-laws": "^1.0.1", | ||
"fantasy-states": "^0.2.1", | ||
"jsverify": "^0.8.3", | ||
"mocha": "^6.0.0", | ||
"nyc": "^13.0.1", | ||
"mocha": "^6.1.2", | ||
"nyc": "^14.1.0", | ||
"ramda": "^0.26.1", | ||
@@ -88,3 +87,4 @@ "remark-cli": "^6.0.0", | ||
"sanctuary-benchmark": "^1.0.0", | ||
"sanctuary-type-classes": "^10.0.0", | ||
"sanctuary-either": "^1.1.0", | ||
"sanctuary-type-classes": "^11.0.0", | ||
"typescript": "^3.0.3", | ||
@@ -91,0 +91,0 @@ "xyz": "^3.0.0" |
1310
README.md
@@ -17,2 +17,10 @@ # [![Fluture](logo.png)](#butterfly) | ||
## :warning: BETA :warning: | ||
You're looking at the _beta_ version of the Fluture documentation. | ||
For the stable version, please consult the | ||
[11.x branch](https://github.com/fluture-js/Fluture/tree/11.x). | ||
---- | ||
Fluture offers a control structure similar to Promises, Tasks, Deferreds, and | ||
@@ -59,13 +67,13 @@ what-have-you. Let's call them Futures. | ||
```js | ||
import {readFile} from 'fs'; | ||
import {node, encase} from 'fluture'; | ||
import {readFile} from 'fs' | ||
import {node, encase, chain, map, fork} from 'fluture' | ||
var getPackageName = file => | ||
node(done => { readFile(file, 'utf8', done) }) | ||
.chain(encase(JSON.parse)) | ||
.map(x => x.name); | ||
const getPackageName = file => ( | ||
node (done => { readFile (file, 'utf8', done) }) | ||
.pipe (chain (encase (JSON.parse))) | ||
.pipe (map (x => x.name)) | ||
) | ||
getPackageName('package.json') | ||
.fork(console.error, console.log); | ||
//> "fluture" | ||
getPackageName ('package.json') | ||
.pipe (fork (console.error) (console.log)) | ||
``` | ||
@@ -79,17 +87,14 @@ | ||
<!-- eslint-disable no-var --> | ||
<!-- eslint-disable padding-line-between-statements --> | ||
```js | ||
var fs = require('fs'); | ||
var Future = require('fluture'); | ||
const fs = require ('fs') | ||
const 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 }); | ||
}; | ||
const getPackageName = function (file) { | ||
return Future.node (function (done) { fs.readFile (file, 'utf8', done) }) | ||
.pipe (Future.chain (Future.encase (JSON.parse))) | ||
.pipe (Future.map (function (x) { return x.name })) | ||
} | ||
getPackageName('package.json') | ||
.fork(console.error, console.log); | ||
//> "fluture" | ||
getPackageName ('package.json') | ||
.pipe (Future.fork (console.error) (console.log)) | ||
``` | ||
@@ -100,3 +105,3 @@ | ||
Fluture is hosted in full with all of its dependencies at | ||
https://cdn.jsdelivr.net/gh/fluture-js/Fluture@11.0.1/dist/bundle.js | ||
https://cdn.jsdelivr.net/gh/fluture-js/Fluture@12.0.0-beta.0/dist/bundle.js | ||
@@ -108,9 +113,7 @@ This script will add `Fluture` to the global scope. | ||
[<img src="https://raw.github.com/fantasyland/fantasy-land/master/logo.png" align="right" width="82" height="82" alt="Fantasy Land" />][FL] | ||
[<img src="https://raw.githubusercontent.com/rpominov/static-land/master/logo/logo.png" align="right" height="82" alt="Static Land" />][6] | ||
* `Future` implements [Fantasy Land][FL] and [Static Land][6] -compatible | ||
* `Future` implements [Fantasy Land][FL] 1.0+ -compatible | ||
`Alt`, `Bifunctor`, `Monad`, and `ChainRec` | ||
(`of`, `ap`, `alt`, `map`, `bimap`, `chain`, `chainRec`). | ||
All versions of Fantasy Land are supported. | ||
* `Future.Par` implements [Fantasy Land 3][FL] and [Static Land][6] -compatible | ||
* `Future.Par` implements [Fantasy Land 3][FL] -compatible | ||
`Alternative` (`of`, `zero`, `map`, `ap`, `alt`). | ||
@@ -149,13 +152,12 @@ * The Future and ConcurrentFuture representatives contain `@@type` properties | ||
- [`Future`: Create a possibly cancellable Future](#future) | ||
- [`of`: Create a resolved Future](#of) | ||
- [`resolve`: Create a resolved Future](#resolve) | ||
- [`reject`: Create a rejected Future](#reject) | ||
- [`after`: Create a Future that resolves after a timeout](#after) | ||
- [`rejectAfter`: Create a Future that rejects after a timeout](#rejectafter) | ||
- [`do`: Create a "coroutine" using a generator function](#do) | ||
- [`try`: Create a Future using a possibly throwing function](#try) | ||
- [`tryP`: Create a Future using a Promise-returning function](#tryp) | ||
- [`go`: Create a "coroutine" using a generator function](#go) | ||
- [`attempt`: Create a Future using a possibly throwing function](#attempt) | ||
- [`attemptP`: Create a Future using a Promise-returning function](#attemptp) | ||
- [`node`: Create a Future using a Node-style callback](#node) | ||
- [`encase`: Convert a possibly throwing function to a Future function](#encase) | ||
- [`encaseP`: Convert a Promise-returning function to a Future function](#encasep) | ||
- [`encaseN`: Convert a Nodeback function to a Future function](#encasen) | ||
@@ -167,3 +169,2 @@ </details> | ||
- [`node`: Create a Future using a Node-style callback](#node) | ||
- [`encaseN`: Convert a Nodeback function to a Future function](#encasen) | ||
- [`done`: Consume a Future by providing a Nodeback](#done) | ||
@@ -175,3 +176,3 @@ | ||
- [`tryP`: Create a Future using a Promise-returning function](#tryp) | ||
- [`attemptP`: Create a Future using a Promise-returning function](#attemptp) | ||
- [`encaseP`: Convert a Promise-returning function to a Future function](#encasep) | ||
@@ -195,3 +196,3 @@ - [`promise`: Convert a Future to a Promise](#promise) | ||
- [`alt`: Logical *or* for Futures](#alt) | ||
- [`finally`: Run a Future after the previous settles](#finally) | ||
- [`lastly`: Run a Future after the previous settles](#lastly) | ||
- [`race`: Race two Futures against each other](#race) | ||
@@ -226,3 +227,3 @@ - [`both`: Await both success values from two Futures](#both) | ||
- [`hook`: Safely create and dispose resources](#hook) | ||
- [`finally`: Run a Future after the previous settles](#finally) | ||
- [`lastly`: Run a Future after the previous settles](#lastly) | ||
@@ -246,48 +247,4 @@ </details> | ||
Hindley-Milner notation. Read about [Hindley-Milner in JavaScript][Guide:HM] | ||
here. On top of the basic Hindley-Milner notation, we use a few additions to | ||
describe the JavaScript-specific stuff, like [methods](#squiggly-arrows) | ||
or functions that take [multiple arguments at once](#brackets). | ||
here. | ||
#### Squiggly Arrows | ||
In order to document *methods*, we use the squiggly arrow (`~>`). This | ||
separates the implicit `this` argument from the other, explicit, arguments. | ||
For example, the following line signifies a method, as indicated by the | ||
squiggly arrow: | ||
```hs | ||
Future.prototype.map :: Future a b ~> (b -> c) -> Future a c | ||
``` | ||
For comparison, the following example shows a regular function: | ||
```hs | ||
map :: (b -> c) -> Future a b -> Future a c | ||
``` | ||
#### Brackets | ||
Most functions exposed by Fluture are curried. This is reflected in their type | ||
signatures by using an arrow at each step where partial application is | ||
possible. For example, the following line signifies a *curried* function, | ||
because it has an arrow after each function argument: | ||
```hs | ||
add :: Number -> Number -> Number | ||
``` | ||
We could have chosen to write the above line with "groups of one argument", but | ||
we usually leave the grouping brackets out for brevity: | ||
```hs | ||
add :: (Number) -> (Number) -> Number | ||
``` | ||
In order to document functions and methods that are *not* curried, we use | ||
grouping to show which arguments have to be provided at the same time: | ||
```hs | ||
add :: (Number, Number) -> Number | ||
``` | ||
#### Types | ||
@@ -342,19 +299,19 @@ | ||
// We use the Future constructor to create a Future instance. | ||
var eventualAnswer = Future(function computeTheAnswer(rej, res){ | ||
const eventualAnswer = Future (function computeTheAnswer (rej, res) { | ||
// We give the computer time to think about the answer, which is 42. | ||
var timeoutId = setTimeout(res, 60000, 42); | ||
const timeoutId = setTimeout (res, 60000, 42) | ||
// Here is how we handle cancellation. This signal is received when nobody | ||
// is interested in the answer any more. | ||
return function onCancel(){ | ||
return function onCancel () { | ||
// Clearing the timeout releases the resources we were holding. | ||
clearTimeout(timeoutId); | ||
}; | ||
clearTimeout (timeoutId) | ||
} | ||
}); | ||
}) | ||
// Now, let's fork our computation and wait for an answer. Forking gives us | ||
// the unsubscribe function. | ||
var unsubscribe = eventualAnswer.fork(console.error, console.log); | ||
const unsubscribe = fork (log ('rejection')) (log ('resolution')) (eventualAnswer) | ||
@@ -364,3 +321,3 @@ // After some time passes, we might not care about the answer any more. | ||
// and trigger the onCancel function. | ||
unsubscribe(); | ||
unsubscribe () | ||
``` | ||
@@ -385,21 +342,22 @@ | ||
```js | ||
var add1 = x => x + 1; | ||
var m = Future.of(1); | ||
> const add1 = x => x + 1 | ||
for(var i = 0; i < 100000; i++){ | ||
m = m.map(add1); | ||
} | ||
> const m = resolve (1) | ||
m.fork(console.error, console.log); | ||
//> 100001 | ||
> for (const i = 0; i < 100000; i++) { | ||
. m = map (add1) (m) | ||
. } | ||
> fork (log ('rejection')) (log ('resolution')) (m) | ||
[resolution]: 100001 | ||
``` | ||
```js | ||
var m = (function recur(x){ | ||
var mx = Future.of(x + 1); | ||
return x < 100000 ? mx.chain(recur) : mx; | ||
}(1)); | ||
> const m = (function recur (x) { | ||
. const mx = resolve (x + 1) | ||
. return x < 100000 ? chain (recur) (mx) : mx | ||
. }(1)) | ||
m.fork(console.error, console.log); | ||
//> 100001 | ||
> fork (log ('rejection')) (log ('resolution')) (m) | ||
[resolution]: 100001 | ||
``` | ||
@@ -454,7 +412,9 @@ | ||
```js | ||
var S = require('sanctuary'); | ||
var Future = require('fluture'); | ||
S.I(Future.of(1)); | ||
//! Since there is no type of which all the above values are members, | ||
//! the type-variable constraint has been violated. | ||
> import S from 'sanctuary' | ||
> import {resolve} from 'fluture' | ||
> S.I (resolve (1)) | ||
! TypeError: Since there is no type of which all the above values are members, | ||
. the type-variable constraint has been violated. | ||
``` | ||
@@ -469,10 +429,14 @@ | ||
```js | ||
var {create, env} = require('sanctuary'); | ||
var {env: flutureEnv} = require('fluture-sanctuary-types'); | ||
var Future = require('fluture'); | ||
> import sanctuary from 'sanctuary' | ||
var S = create({checkTypes: true, env: env.concat(flutureEnv)}); | ||
> import {env as flutureEnv} from 'fluture-sanctuary-types' | ||
S.I(Future.of(1)); | ||
//> Future.of(1) | ||
> import {resolve} from 'fluture' | ||
> const S = sanctuary.create ({checkTypes: true, env: env.concat (flutureEnv)}) | ||
> fork (log ('rejection')) | ||
. (log ('resolution')) | ||
. (S.I (resolve (42))) | ||
[resolution]: 42 | ||
``` | ||
@@ -489,10 +453,12 @@ | ||
```js | ||
var NoFuture = require('incompatible-future'); | ||
var incompatible = NoFuture.of('Hello'); | ||
> const NoFuture = require ('incompatible-future') | ||
//Cast the incompatible Future to our version of Future: | ||
var compatible = Future(incompatible.fork.bind(incompatible)); | ||
> const incompatible = NoFuture.of ('Hello') | ||
compatible.both(Future.of('world')).value(console.log); | ||
//> ["Hello", "world"] | ||
> const compatible = Future (incompatible.fork.bind (incompatible)) | ||
> fork (log ('rejection')) | ||
. (log ('resolution')) | ||
. (both (compatible) (resolve ('world'))) | ||
[resolution]: ["Hello", "world"] | ||
``` | ||
@@ -504,4 +470,2 @@ | ||
<details><summary><code>Future :: ((a -> Undefined, b -> Undefined) -> Cancel) -> Future a b</code></summary> | ||
```hs | ||
@@ -511,4 +475,2 @@ Future :: ((a -> Undefined, b -> Undefined) -> Cancel) -> Future a b | ||
</details> | ||
Creates a Future with the given computation. A computation is a function which | ||
@@ -524,31 +486,23 @@ takes two callbacks. Both are continuations for the computation. The first is | ||
```js | ||
Future(function computation(reject, resolve){ | ||
setTimeout(resolve, 3000, 'world'); | ||
}); | ||
> fork (log ('rejection')) | ||
. (log ('resolution')) | ||
. (Future (function computation (reject, resolve) { | ||
. setTimeout (resolve, 20, 42) | ||
. })) | ||
[resolution]: 42 | ||
``` | ||
#### of | ||
#### resolve | ||
<details><summary><code>of :: b -> Future a b</code></summary> | ||
```hs | ||
of :: b -> Future a b | ||
resolve :: b -> Future a b | ||
Future.of :: b -> Future a b | ||
Future.resolve :: b -> Future a b | ||
resolve :: b -> Future a b | ||
``` | ||
</details> | ||
Creates a Future which immediately resolves with the given value. | ||
This function has an alias `resolve`. | ||
```js | ||
var eventualThing = Future.of('world'); | ||
eventualThing.fork( | ||
console.error, | ||
thing => console.log(`Hello ${thing}!`) | ||
); | ||
//> "Hello world!" | ||
> fork (log ('rejection')) | ||
. (log ('resolution')) | ||
. (resolve (42)) | ||
[answer]: 42 | ||
``` | ||
@@ -558,20 +512,13 @@ | ||
<details><summary><code>reject :: a -> Future a b</code></summary> | ||
```hs | ||
reject :: a -> Future a b | ||
Future.reject :: a -> Future a b | ||
reject :: a -> Future a b | ||
``` | ||
</details> | ||
Creates a Future which immediately rejects with the given value. | ||
```js | ||
var eventualFailure = Future.reject('I got so far!'); | ||
eventualFailure.fork( | ||
e => console.error('I tried so hard!', e), | ||
console.log | ||
); | ||
//! "I tried so hard! I got so far!" | ||
> fork (log ('rejection')) | ||
. (log ('resolution')) | ||
. (reject ('It broke!')) | ||
[rejection]: "It broke!" | ||
``` | ||
@@ -581,4 +528,2 @@ | ||
<details><summary><code>after :: Number -> b -> Future a b</code></summary> | ||
```hs | ||
@@ -588,11 +533,10 @@ after :: Number -> b -> Future a b | ||
</details> | ||
Creates a Future which resolves with the given value after | ||
the given number of milliseconds. | ||
Creates a Future which resolves with the given value after the given number of | ||
milliseconds. | ||
```js | ||
var eventualThing = Future.after(500, 'world'); | ||
eventualThing.fork(console.error, thing => console.log(`Hello ${thing}!`)); | ||
//> "Hello world!" | ||
> fork (log ('rejection')) | ||
. (log ('resolution')) | ||
. (after (20) (42)) | ||
[resolution]: 42 | ||
``` | ||
@@ -602,4 +546,2 @@ | ||
<details><summary><code>rejectAfter :: Number -> a -> Future a b</code></summary> | ||
```hs | ||
@@ -609,4 +551,2 @@ rejectAfter :: Number -> a -> Future a b | ||
</details> | ||
Creates a Future which rejects with the given reason after the given number of | ||
@@ -616,18 +556,14 @@ milliseconds. | ||
```js | ||
var eventualError = Future.rejectAfter(500, new Error('Kaputt!')); | ||
eventualError.fork(err => console.log('Oh no - ' + err.message), console.log); | ||
//! Oh no - Kaputt! | ||
> fork (log ('rejection')) | ||
. (log ('resolution')) | ||
. (rejectAfter (20) ('It broke!')) | ||
[rejection]: "It broke!" | ||
``` | ||
#### do | ||
#### go | ||
<details><summary><code>do :: (() -> Iterator) -> Future a b</code></summary> | ||
```hs | ||
do :: (() -> Iterator) -> Future a b | ||
go :: (() -> Iterator) -> Future a b | ||
``` | ||
</details> | ||
A way to do `async`/`await` with Futures, similar to Promise Coroutines or | ||
@@ -639,80 +575,75 @@ Haskell Do-notation. | ||
This function has an alias `go`, for environments where `do` is reserved. | ||
```js | ||
> fork (log ('rejection')) (log ('resolution')) (go (function*() { | ||
. const thing = yield after (20) ('world') | ||
. const message = yield after (20) ('Hello ' + thing) | ||
. return message + '!' | ||
. })) | ||
[resolution]: "Hello world!" | ||
``` | ||
A rejected Future short-circuits the whole coroutine. | ||
```js | ||
var eventualMessage = Future.do(function*(){ | ||
var thing = yield Future.after(300, 'world'); | ||
var message = yield Future.after(300, 'Hello ' + thing); | ||
return message + '!'; | ||
}); | ||
eventualMessage.fork(console.error, console.log); | ||
//After 600ms: | ||
//> "Hello world!" | ||
> fork (log ('rejection')) (log ('resolution')) (go (function*() { | ||
. const thing = yield reject ('It broke!') | ||
. const message = yield after (20) ('Hello ' + thing) | ||
. return message + '!' | ||
. })) | ||
[rejection]: "It broke!" | ||
``` | ||
To handle errors inside a `do` procedure, we need to [`fold`](#fold) the error | ||
into our control domain, I recommend folding into an [`Either`][S:Either]: | ||
To handle rejections *inside* the coroutine, we need to [`fold`](#fold) the | ||
error into our control domain. | ||
I recommend folding into an [`Either`][S:Either]. | ||
```js | ||
var attempt = Future.fold(S.Left, S.Right); | ||
var ajaxGet = url => Future.reject('Failed to load ' + url); | ||
> const control = fold (S.Left) (S.Right) | ||
var eventualMessage = Future.do(function*(){ | ||
var e = yield attempt(ajaxGet('/message')); | ||
return S.either( | ||
e => `Oh no! ${e}`, | ||
x => `Yippee! ${x}`, | ||
e | ||
); | ||
}); | ||
eventualMessage.fork(console.error, console.log); | ||
//> "Oh no! Failed to load /message" | ||
> fork (log ('rejection')) (log ('resolution')) (go (function*() { | ||
. const thing = yield control (reject ('It broke!')) | ||
. return S.either (x => `Oh no! ${x}`) | ||
. (x => `Yippee! ${x}`) | ||
. (thing) | ||
. })) | ||
[resolution]: "Oh no! It broke!" | ||
``` | ||
#### try | ||
#### attempt | ||
<details><summary><code>try :: Catchable e (() -> r) -> Future e r</code></summary> | ||
```hs | ||
try :: Catchable e (() -> r) -> Future e r | ||
attempt :: Catchable e (() -> r) -> Future e r | ||
attempt :: Catchable e (Undefined -> r) -> Future e r | ||
``` | ||
</details> | ||
Creates a Future which resolves with the result of calling the given function, | ||
or rejects with the error thrown by the given function. | ||
Short for [`Future.encase(f, undefined)`](#encase). | ||
Short for [`encase (f) (undefined)`](#encase). | ||
This function has an alias `attempt`, for environments where `try` is reserved. | ||
```js | ||
> const data = {foo: 'bar'} | ||
```js | ||
var data = {foo: 'bar'}; | ||
Future.try(() => data.foo.bar.baz) | ||
.fork(console.error, console.log); | ||
//> [TypeError: Cannot read property 'baz' of undefined] | ||
> fork (log ('rejection')) | ||
. (log ('resolution')) | ||
. (attempt (() => data.foo.bar.baz)) | ||
[rejection]: new TypeError ("Cannot read property 'baz' of undefined") | ||
``` | ||
#### tryP | ||
#### attemptP | ||
<details><summary><code>tryP :: (() -> Promise e r) -> Future e r</code></summary> | ||
```hs | ||
tryP :: (() -> Promise e r) -> Future e r | ||
attemptP :: (Undefined -> Promise e r) -> Future e r | ||
``` | ||
</details> | ||
Create a Future which when forked spawns a Promise using the given function and | ||
resolves with its resolution value, or rejects with its rejection reason. | ||
Short for [`Future.encaseP(f, undefined)`](#encasep). | ||
Short for [`encaseP (f) (undefined)`](#encasep). | ||
```js | ||
Future.tryP(() => Promise.resolve('Hello')) | ||
.fork(console.error, console.log); | ||
//> "Hello" | ||
> fork (log ('rejection')) | ||
. (log ('resolution')) | ||
. (attemptP (() => Promise.resolve (42))) | ||
[resolution]: 42 | ||
``` | ||
@@ -722,4 +653,2 @@ | ||
<details><summary><code>node :: (Nodeback e r -> x) -> Future e r</code></summary> | ||
```hs | ||
@@ -729,4 +658,2 @@ node :: (Nodeback e r -> x) -> Future e r | ||
</details> | ||
Creates a Future which rejects with the first argument given to the function, | ||
@@ -737,10 +664,7 @@ or resolves with the second if the first is not present. | ||
Short for [`Future.encaseN(f, undefined)`](#encasen). | ||
```js | ||
Future.node(done => { | ||
done(null, 'Hello'); | ||
}) | ||
.fork(console.error, console.log); | ||
//> "Hello" | ||
> fork (log ('rejection')) | ||
. (log ('resolution')) | ||
. (node (done => done (null, 42))) | ||
[resolution]: 42 | ||
``` | ||
@@ -750,28 +674,18 @@ | ||
<details><summary><code>encase :: (Catchable e (a -> r)) -> a -> Future e r</code></summary> | ||
```hs | ||
encase :: (Catchable e ((a ) -> r)) -> a -> Future e r | ||
encase2 :: (Catchable e ((a, b ) -> r)) -> a -> b -> Future e r | ||
encase3 :: (Catchable e ((a, b, c) -> r)) -> a -> b -> c -> Future e r | ||
encase :: (Catchable e (a -> r)) -> a -> Future e r | ||
``` | ||
</details> | ||
Takes a function and a value, and returns a Future which when forked calls the | ||
function with the value and resolves with the result. If the function throws | ||
an exception, it is caught and the Future will reject with the exception: | ||
an exception, it is caught and the Future will reject with the exception. | ||
Partially applying `encase` with a function `f` allows us to create a "safe" | ||
version of `f`. Instead of throwing exceptions, the encased version always | ||
returns a Future when given the remaining argument(s): | ||
Applying `encase` with a function `f` creates a "safe" version of `f`. Instead | ||
of throwing exceptions, the encased version always returns a Future. | ||
Furthermore; `encase2` and `encase3` are binary and ternary versions of | ||
`encase`, applying two or three arguments to the given function respectively. | ||
```js | ||
var data = '{"foo" = "bar"}'; | ||
var safeJsonParse = Future.encase(JSON.parse); | ||
safeJsonParse(data).fork(console.error, console.log); | ||
//! [SyntaxError: Unexpected token =] | ||
> fork (log ('rejection')) | ||
. (log ('resolution')) | ||
. (encase (JSON.parse) ('{"foo" = "bar"}')) | ||
[rejection]: new SyntaxError ('Unexpected token =') | ||
``` | ||
@@ -781,15 +695,8 @@ | ||
<details><summary><code>encaseP :: ((a) -> Promise e r) -> a -> Future e r</code></summary> | ||
```hs | ||
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 | ||
encaseP :: (a -> Promise e r) -> a -> Future e r | ||
``` | ||
</details> | ||
Turns Promise-returning functions into Future-returning functions. | ||
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. | ||
@@ -800,64 +707,10 @@ When forked, the Future calls the function with the value to produce the | ||
Furthermore; `encaseP2` and `encaseP3` are binary and ternary versions of | ||
`encaseP`, applying two or three arguments to the given function respectively. | ||
```js | ||
var fetchf = Future.encaseP(fetch); | ||
fetchf('https://api.github.com/users/Avaq') | ||
.chain(res => Future.tryP(_ => res.json())) | ||
.map(user => user.name) | ||
.fork(console.error, console.log); | ||
//> "Aldwin Vlasblom" | ||
> encaseP (fetch) ('https://api.github.com/users/Avaq') | ||
. .pipe (chain (encaseP (res => res.json ()))) | ||
. .pipe (map (user => user.name)) | ||
. .pipe (fork (log ('rejection')) (log ('resolution'))) | ||
[resolution]: "Aldwin Vlasblom" | ||
``` | ||
#### encaseN | ||
<details><summary><code>encaseN :: ((a, Nodeback e r) -> x) -> a -> Future e r</code></summary> | ||
```hs | ||
encaseN :: ((a, Nodeback e r) -> x) -> a -> Future e r | ||
encaseN2 :: ((a, b, Nodeback e r) -> x) -> a -> b -> Future e r | ||
encaseN3 :: ((a, b, c, Nodeback e r) -> x) -> a -> b -> c -> Future e r | ||
``` | ||
</details> | ||
Allows [continuation-passing-style][1] functions to be turned into | ||
Future-returning functions. | ||
Takes a function which accepts as its last parameter a [Nodeback](#types), and | ||
a value, and returns a Future. When forked, the Future calls the function with | ||
the value and a Nodeback and resolves the second argument passed to the | ||
Nodeback, or or rejects with the first argument. | ||
Furthermore; `encaseN2` and `encaseN3` are binary and ternary versions of | ||
`encaseN`, applying two or three arguments to the given function respectively. | ||
```js | ||
var fs = require('fs'); | ||
var read = Future.encaseN2(fs.readFile); | ||
read('README.md', 'utf8') | ||
.map(text => text.split('\n')) | ||
.map(lines => lines[0]) | ||
.fork(console.error, console.log); | ||
//> "# [![Fluture](logo.png)](#butterfly)" | ||
``` | ||
#### chainRec | ||
<details><summary><code>Future.chainRec :: ((a -> Next a, b -> Done b, a) -> Future e (Next a | Done b), a) -> Future e b</code></summary> | ||
```hs | ||
Future.chainRec :: ((a -> Next a, b -> Done b, a) -> Future e (Next a | Done b), a) -> Future e b | ||
``` | ||
</details> | ||
Implementation of [Fantasy Land ChainRec][FL:chainrec]. Since Fluture 6.0 | ||
introduced [stack safety](#stack-safety) there should be no need to use this | ||
function directly. Instead it's recommended to use [`chain(rec)`](#chain). | ||
### Transforming Futures | ||
@@ -867,24 +720,18 @@ | ||
<details><summary><code>map :: Functor m => (a -> b) -> m a -> m b</code></summary> | ||
```hs | ||
map :: Functor m => (a -> b) -> m a -> m b | ||
Future.map :: Functor m => (a -> b) -> m a -> m b | ||
Par.map :: Functor m => (a -> b) -> m a -> m b | ||
Future.prototype.map :: Future e a ~> (a -> b) -> Future e b | ||
map :: Functor m => (a -> b) -> m a -> m b | ||
``` | ||
</details> | ||
Transforms the resolution value inside the Future or [Functor][FL:functor], | ||
and returns a Future or Functor with the new value. The transformation is only | ||
applied to the resolution branch: if the Future is rejected, the transformation | ||
is ignored. | ||
Transforms the resolution value inside the Future, and returns a Future with | ||
the new value. The transformation is only applied to the resolution branch: if | ||
the Future is rejected, the transformation is ignored. | ||
See also [`chain`](#chain) and [`mapRej`](#maprej). | ||
```js | ||
Future.of(1) | ||
.map(x => x + 1) | ||
.fork(console.error, console.log); | ||
//> 2 | ||
> fork (log ('rejection')) | ||
. (log ('resolution')) | ||
. (map (x => x + 1) (resolve (41))) | ||
[resolution]: 42 | ||
``` | ||
@@ -895,5 +742,6 @@ | ||
```js | ||
Promise.resolve(1) | ||
.then(x => x + 1) | ||
.then(console.log, console.error); | ||
> Promise.resolve (41) | ||
. .then (x => x + 1) | ||
. .then (log ('resolution'), log ('rejection')) | ||
[resolution]: 42 | ||
``` | ||
@@ -903,25 +751,20 @@ | ||
<details><summary><code>bimap :: Bifunctor m => (a -> c) -> (b -> d) -> m a b -> m c d</code></summary> | ||
```hs | ||
bimap :: Bifunctor m => (a -> c) -> (b -> d) -> m a b -> m c d | ||
Future.bimap :: Bifunctor m => (a -> c) -> (b -> d) -> m a b -> m c d | ||
Future.prototype.bimap :: Future a b ~> (a -> c, b -> d) -> Future c d | ||
bimap :: Bifunctor m => (a -> c) -> (b -> d) -> m a b -> m c d | ||
``` | ||
</details> | ||
Maps the left function over the rejection reason, or the right function over | ||
the resolution value, depending on which is present. Can be used on any | ||
[Bifunctor][FL:bifunctor]. | ||
Maps the left function over the rejection value, or the right function over the | ||
resolution value, depending on which is present. | ||
```js | ||
Future.of(1) | ||
.bimap(x => x + '!', x => x + 1) | ||
.fork(console.error, console.log); | ||
//> 2 | ||
> fork (log ('rejection')) | ||
. (log ('resolution')) | ||
. (bimap (x => x + '!') (x => x + 1) (resolve (41))) | ||
[resolution]: 42 | ||
Future.reject('error') | ||
.bimap(x => x + '!', x => x + 1) | ||
.fork(console.error, console.log); | ||
//! "error!" | ||
> fork (log ('rejection')) | ||
. (log ('resolution')) | ||
. (bimap (x => x + '!') (x => x + 1) (reject ('It broke!'))) | ||
[rejection]: "It broke!!" | ||
``` | ||
@@ -932,5 +775,6 @@ | ||
```js | ||
Promise.resolve(1) | ||
.then(x => x + 1, x => x + '!') | ||
.then(console.log, console.error); | ||
> Promise.resolve (41) | ||
. .then (x => x + 1, x => x + '!') | ||
. .then (log ('resolution'), log ('rejection')) | ||
[resolution]: 42 | ||
``` | ||
@@ -940,17 +784,11 @@ | ||
<details><summary><code>chain :: Chain m => (a -> m b) -> m a -> m b</code></summary> | ||
```hs | ||
chain :: Chain m => (a -> m b) -> m a -> m b | ||
Future.chain :: Chain m => (a -> m b) -> m a -> m b | ||
Future.prototype.chain :: Future e a ~> (a -> Future e b) -> Future e b | ||
chain :: Chain m => (a -> m b) -> m a -> m b | ||
``` | ||
</details> | ||
Sequence a new Future or [Chain][FL:chain] using the resolution value from | ||
another. Similarly to [`map`](#map), `chain` expects a function. But instead | ||
of returning the new *value*, chain expects a Future (or instance of the same | ||
Chain) to be returned. | ||
Sequence a new Future using the resolution value from another. Similarly to | ||
[`map`](#map), `chain` expects a function to transform the resolution value of | ||
a Future. But instead of returning the new *value*, chain expects a Future to | ||
be returned. | ||
The transformation is only applied to the resolution branch: if the Future is | ||
@@ -962,6 +800,6 @@ rejected, the transformation is ignored. | ||
```js | ||
Future.of(1) | ||
.chain(x => Future.of(x + 1)) | ||
.fork(console.error, console.log); | ||
//> 2 | ||
> fork (log ('rejection')) | ||
. (log ('resolution')) | ||
. (chain (x => resolve (x + 1)) (resolve (41))) | ||
[resolution]: 42 | ||
``` | ||
@@ -972,5 +810,6 @@ | ||
```js | ||
Promise.resolve(1) | ||
.then(x => Promise.resolve(x + 1)) | ||
.then(console.log, console.error); | ||
> Promise.resolve (41) | ||
. .then (x => Promise.resolve (x + 1)) | ||
. .then (log ('resolution'), log ('rejection')) | ||
[resolution]: 42 | ||
``` | ||
@@ -980,19 +819,18 @@ | ||
<details><summary><code>swap :: Future a b -> Future b a</code></summary> | ||
```hs | ||
swap :: Future a b -> Future b a | ||
Future.prototype.swap :: Future a b ~> Future b a | ||
swap :: Future a b -> Future b a | ||
``` | ||
</details> | ||
Swap the rejection and resolution branches. | ||
Resolve with the rejection reason, or reject with the resolution value. | ||
```js | ||
Future.of(new Error('It broke')).swap().fork(console.error, console.log); | ||
//! [It broke] | ||
> fork (log ('rejection')) | ||
. (log ('resolution')) | ||
. (swap (resolve (42))) | ||
[rejection]: 42 | ||
Future.reject('Nothing broke').swap().fork(console.error, console.log); | ||
//> "Nothing broke" | ||
> fork (log ('rejection')) | ||
. (log ('resolution')) | ||
. (swap (reject (42))) | ||
[resolution]: 42 | ||
``` | ||
@@ -1002,11 +840,6 @@ | ||
<details><summary><code>mapRej :: (a -> c) -> Future a b -> Future c b</code></summary> | ||
```hs | ||
mapRej :: (a -> c) -> Future a b -> Future c b | ||
Future.prototype.mapRej :: Future a b ~> (a -> c) -> Future c b | ||
mapRej :: (a -> c) -> Future a b -> Future c b | ||
``` | ||
</details> | ||
Map over the **rejection** reason of the Future. This is like [`map`](#map), | ||
@@ -1016,6 +849,6 @@ but for the rejection branch. | ||
```js | ||
Future.reject(new Error('It broke!')) | ||
.mapRej(err => new Error('Oh No! ' + err.message)) | ||
.fork(console.error, console.log); | ||
//! [Oh No! It broke!] | ||
> fork (log ('rejection')) | ||
. (log ('resolution')) | ||
. (mapRej (s => `Oh no! ${s}`) (reject ('It broke!'))) | ||
[rejection]: "Oh no! It broke!" | ||
``` | ||
@@ -1026,5 +859,6 @@ | ||
```js | ||
Promise.resolve(1) | ||
.then(null, err => Promise.reject(new Error('Oh No! ' + err.message))) | ||
.then(console.log, console.error); | ||
> Promise.reject ('It broke!') | ||
. .then (null, s => Promise.reject (`Oh no! ${s}`)) | ||
. .then (log ('resolution'), log ('rejection')) | ||
[rejection]: "Oh no! It broke!" | ||
``` | ||
@@ -1034,11 +868,6 @@ | ||
<details><summary><code>chainRej :: (a -> Future c b) -> Future a b -> Future c b</code></summary> | ||
```hs | ||
chainRej :: (a -> Future c b) -> Future a b -> Future c b | ||
Future.prototype.chainRej :: Future a b ~> (a -> Future c b) -> Future c b | ||
chainRej :: (a -> Future c b) -> Future a b -> Future c b | ||
``` | ||
</details> | ||
Chain over the **rejection** reason of the Future. This is like | ||
@@ -1048,6 +877,6 @@ [`chain`](#chain), but for the rejection branch. | ||
```js | ||
Future.reject(new Error('It broke!')) | ||
.chainRej(err => Future.of(err.message + ' But it\'s all good.')) | ||
.fork(console.error, console.log); | ||
//> "It broke! But it's all good." | ||
> fork (log ('rejection')) | ||
. (log ('resolution')) | ||
. (chainRej (s => resolve (`${s} But it's all good.`))) | ||
[resolution]: "It broke! But it's all good." | ||
``` | ||
@@ -1058,5 +887,6 @@ | ||
```js | ||
Promise.reject(new Error('It broke!')) | ||
.then(null, err => err.message + ' But it\'s all good.') | ||
.then(console.log, console.error); | ||
> Promise.reject ('It broke!') | ||
. .then (null, s => `${s} But it's all good.`) | ||
. .then (log ('resolution'), log ('rejection')) | ||
[resolution]: "It broke! But it's all good." | ||
``` | ||
@@ -1066,11 +896,6 @@ | ||
<details><summary><code>fold :: (a -> c) -> (b -> c) -> Future a b -> Future d c</code></summary> | ||
```hs | ||
fold :: (a -> c) -> (b -> c) -> Future a b -> Future d c | ||
Future.prototype.fold :: Future a b ~> (a -> c, b -> c) -> Future d c | ||
fold :: (a -> c) -> (b -> c) -> Future a b -> Future d c | ||
``` | ||
</details> | ||
Applies the left function to the rejection value, or the right function to the | ||
@@ -1084,11 +909,11 @@ resolution value, depending on which is present, and resolves with the result. | ||
```js | ||
Future.of('hello') | ||
.fold(S.Left, S.Right) | ||
.value(console.log); | ||
//> Right('hello') | ||
> fork (log ('rejection')) | ||
. (log ('resolution')) | ||
. (fold (S.Left) (S.Right) (resolve ('hello')) | ||
[resolution]: Right ("hello") | ||
Future.reject('it broke') | ||
.fold(S.Left, S.Right) | ||
.value(console.log); | ||
//> Left('it broke') | ||
> fork (log ('rejection')) | ||
. (log ('resolution')) | ||
. (fold (S.Left) (S.Right) (reject ('It broke!')) | ||
[resolution]: Left ("It broke!") | ||
``` | ||
@@ -1099,5 +924,6 @@ | ||
```js | ||
Promise.resolve('hello') | ||
.then(S.Right, S.Left) | ||
.then(console.log); | ||
> Promise.resolve ('hello') | ||
. .then (S.Right, S.Left) | ||
. .then (log ('resolution'), log ('rejection')) | ||
[resolution]: Right ("hello") | ||
``` | ||
@@ -1109,123 +935,100 @@ | ||
<details><summary><code>ap :: Apply m => m (a -> b) -> m a -> m b</code></summary> | ||
```hs | ||
ap :: Apply m => m (a -> b) -> m a -> m b | ||
Future.ap :: Apply m => m (a -> b) -> m a -> m b | ||
Par.ap :: Apply m => m (a -> b) -> m a -> m b | ||
Future.prototype.ap :: Future e (a -> b) ~> Future e a -> Future e b | ||
ap :: Apply m => m a -> m (a -> b) -> m b | ||
``` | ||
</details> | ||
Applies the function contained in the right-hand Future or [Apply][FL:apply] | ||
to the value contained in the left-hand Future or Apply. This process can be | ||
repeated to gradually fill out multiple function arguments of a curried | ||
function, as shown below. | ||
Applies the function contained in the left-hand Future to the value | ||
contained in the right-hand Future. If one of the Futures rejects the | ||
resulting Future will also be rejected. | ||
Note that the Futures will be executed in sequence - not in parallel\* - | ||
because of the Monadic nature of Futures. The execution order is, as | ||
specified by Fantasy Land, `m (a -> b)` first followed by `m a`. | ||
So that's *right before left*. | ||
\* If you'd like to use a parallel implementation of `ap`, you need to use a | ||
non-monadic type. Fluture provides this through [`Par`](#concurrentfuture). | ||
Wrapping your Future instances with `Par` before passing them to `ap` will | ||
cause them to run in parallel! | ||
```js | ||
Future.of(x => y => x + y) | ||
.ap(Future.of(1)) | ||
.ap(Future.of(2)) | ||
.fork(console.error, console.log); | ||
//> 3 | ||
> fork (log ('rejection')) | ||
. (log ('resolution')) | ||
. (ap (resolve (7)) (ap (resolve (49)) (resolve (x => y => x - y)))) | ||
[resolution]: 42 | ||
``` | ||
#### and | ||
#### alt | ||
<details><summary><code>and :: Future a b -> Future a c -> Future a c</code></summary> | ||
```hs | ||
and :: Future a b -> Future a c -> Future a c | ||
Future.prototype.and :: Future a b ~> Future a c -> Future a c | ||
alt :: Alt f => f a -> f a -> f a | ||
``` | ||
</details> | ||
Select one of two [Alts](#types). | ||
Logical *and* for Futures. | ||
Behaves like logical *or* on [`Future`](#future) instances, returning a new | ||
Future which either resolves with the first resolution value, or rejects with | ||
the last rejection reason. We can use it if we want a computation to run only | ||
if another has failed. | ||
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. We | ||
can use it if we want a computation to run only after another has succeeded. | ||
Note that the Futures will be executed in sequence - not in parallel\* - | ||
because of the Monadic nature of Futures. The *right* Future is evaluated | ||
before the *left* Future. | ||
See also [`alt`](#alt) and [`finally`](#finally). | ||
See also [`and`](#and) and [`lastly`](#lastly). | ||
\* If you'd like to use a parallel implementation of `alt`, you could simply | ||
use [`race`](#race). Alternatively you could wrap your Future instances | ||
with [`Par`](#concurrentfuture) before passing them to `alt`. | ||
```js | ||
Future.after(300, null) | ||
.and(Future.of('hello')) | ||
.fork(console.error, console.log); | ||
//> "hello" | ||
``` | ||
> fork (log ('rejection')) | ||
. (log ('resolution')) | ||
. (alt (resolve ('left')) (resolve ('right'))) | ||
[resolution]: "right" | ||
With good old `reduce`, we can turn this into an asynchronous `all` function, | ||
where the resulting Future will be the leftmost to reject, or the rightmost to | ||
resolve. | ||
```js | ||
var all = ms => ms.reduce(Future.and, Future.of(0)); | ||
all([Future.after(20, 1), Future.of(2)]).value(console.log); | ||
//> 2 | ||
> fork (log ('rejection')) | ||
. (log ('resolution')) | ||
. (alt (resolve ('left')) (reject ('It broke!'))) | ||
[resolution]: "left" | ||
``` | ||
#### alt | ||
#### and | ||
<details><summary><code>alt :: Alt f => f a -> f a -> f a</code></summary> | ||
```hs | ||
alt :: Alt f => f a -> f a -> f a | ||
or :: Alt f => f a -> f a -> f a | ||
Future.alt :: Alt f => f a -> f a -> f a | ||
Par.alt :: Alt f => f a -> f a -> f a | ||
Future.prototype.alt :: Future a b ~> Future a b -> Future a b | ||
Future.prototype.or :: Future a b ~> Future a b -> Future a b | ||
and :: Future a c -> Future a b -> Future a c | ||
``` | ||
</details> | ||
Logical *and* for Futures. | ||
Select one of two [Alts](#types). | ||
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. We | ||
can use it if we want a computation to run only after another has succeeded. | ||
The *right* Future is evaluated before the *left* Future. | ||
Behaves like logical *or* on [`Future`](#future) instances, returning a new | ||
Future which either resolves with the first resolution value, or rejects with | ||
the last rejection reason. We can use it if we want a computation to run only | ||
if another has failed. | ||
See also [`alt`](#alt) and [`lastly`](#lastly). | ||
Behaves like [`race`](#race) on [`ConcurrentFuture`](#concurrentfuture) instances. | ||
This function has an alias `or` for legacy reasons. | ||
See also [`and`](#and) and [`finally`](#finally). | ||
```js | ||
Future.rejectAfter(300, new Error('Failed')) | ||
.alt(Future.of('hello')) | ||
.fork(console.error, console.log); | ||
//> "hello" | ||
``` | ||
> fork (log ('rejection')) | ||
. (log ('resolution')) | ||
. (and (resolve ('left')) (resolve ('right'))) | ||
[resolution]: "left" | ||
With good old `reduce`, we can turn this into an asynchronous `any` function, | ||
where the resulting Future will be the leftmost to resolve, or the rightmost | ||
to reject. | ||
```js | ||
var any = ms => ms.reduce(Future.alt, Future.reject('empty list')); | ||
any([Future.reject(1), Future.after(20, 2), Future.of(3)]).value(console.log); | ||
//> 2 | ||
> fork (log ('rejection')) | ||
. (log ('resolution')) | ||
. (and (resolve ('left')) (reject ('It broke!'))) | ||
[rejection]: "It broke!" | ||
``` | ||
#### finally | ||
#### lastly | ||
<details><summary><code>finally :: Future a c -> Future a b -> Future a b</code></summary> | ||
```hs | ||
finally :: Future a c -> Future a b -> Future a b | ||
lastly :: Future a c -> Future a b -> Future a b | ||
Future.prototype.finally :: Future a b ~> Future a c -> Future a b | ||
Future.prototype.lastly :: Future a b ~> Future a c -> Future a b | ||
lastly :: Future a c -> Future a b -> Future a b | ||
``` | ||
</details> | ||
Run a second Future after the first settles (successfully or unsuccessfully). | ||
Rejects with the rejection reason from the first or second Future, or resolves | ||
with the resolution value from the first Future. We can use this when we want | ||
a computation to run after another settles, successfully or unsuccessfully. | ||
with the resolution value from the first Future. This can be used to run a | ||
computation after another settles, successfully or unsuccessfully. | ||
@@ -1236,29 +1039,12 @@ If you're looking to clean up resources after running a computation which | ||
This function has an alias `lastly`, for environments where `finally` is | ||
reserved. | ||
See also [`and`](#and) and [`alt`](#alt). | ||
```js | ||
Future.of('Hello') | ||
.finally(Future.of('All done!').map(console.log)) | ||
.fork(console.error, console.log); | ||
//> "All done!" | ||
//> "Hello" | ||
> fork (log ('rejection')) | ||
. (log ('resolution')) | ||
. (lastly (encase (log ('lastly')) ('All done!')) (resolve (42))) | ||
[lastly]: "All done!" | ||
[resolution]: 42 | ||
``` | ||
Note that the *first* Future is given as the *last* argument to `Future.finally()`: | ||
```js | ||
var program = S.pipe([ | ||
Future.of, | ||
Future.finally(Future.of('All done!').map(console.log)), | ||
Future.fork(console.error, console.log) | ||
]); | ||
program('Hello'); | ||
//> "All done!" | ||
//> "Hello" | ||
``` | ||
### Consuming Futures | ||
@@ -1268,11 +1054,6 @@ | ||
<details><summary><code>fork :: (a -> Any) -> (b -> Any) -> Future a b -> Cancel</code></summary> | ||
```hs | ||
fork :: (a -> Any) -> (b -> Any) -> Future a b -> Cancel | ||
Future.prototype.fork :: Future a b ~> (a -> Any, b -> Any) -> Cancel | ||
fork :: (a -> Any) -> (b -> Any) -> Future a b -> Cancel | ||
``` | ||
</details> | ||
Execute the computation represented by a Future, passing `reject` and `resolve` | ||
@@ -1291,38 +1072,18 @@ callbacks to continue once there is a result. | ||
decides halfway through that it's no longer interested in the result of the | ||
computation, it can call the `unsubscribe` function returned by `fork()`. See | ||
computation, it can call the `unsubscribe` function returned by `fork`. See | ||
[Cancellation](#cancellation). | ||
Note that if an exception was encountered during the computation, it will be | ||
thrown and likely not be catchable. If the computation ran in isolation, we may | ||
want to use [`forkCatch`](#forkcatch) instead to recover from exceptions. | ||
If an exception was encountered during the computation, it will be re-thrown | ||
by `fork` and likely not be catchable. You can handle it using | ||
`process.on('uncaughtException')` in Node, or use [`forkCatch`](#forkcatch). | ||
```js | ||
Future.of('world').fork( | ||
err => console.log(`Oh no! ${err.message}`), | ||
thing => console.log(`Hello ${thing}!`) | ||
); | ||
//> "Hello world!" | ||
Almost all code examples in Fluture use `fork` to run the computation. There | ||
are some variations on `fork` that serve different purposes below. | ||
Future.reject(new Error('It broke!')).fork( | ||
err => console.log(`Oh no! ${err.message}`), | ||
thing => console.log(`Hello ${thing}!`) | ||
); | ||
//! "Oh no! It broke!" | ||
var consoleFork = Future.fork(console.error, console.log); | ||
consoleFork(Future.of('Hello')); | ||
//> "Hello" | ||
``` | ||
#### forkCatch | ||
<details><summary><code>forkCatch :: (Error -> Any) -> (a -> Any) -> (b -> Any) -> Future a b -> Cancel</code></summary> | ||
```hs | ||
forkCatch :: (Error -> Any) -> (a -> Any) -> (b -> Any) -> Future a b -> Cancel | ||
Future.prototype.forkCatch :: Future a b ~> (Error -> Any, a -> Any, b -> Any) -> Cancel | ||
forkCatch :: (Error -> Any) -> (a -> Any) -> (b -> Any) -> Future a b -> Cancel | ||
``` | ||
</details> | ||
An advanced version of [fork](#fork) that allows us to react to a fatal error | ||
@@ -1351,11 +1112,7 @@ in a custom way. Fatal errors occur when unexpected exceptions are thrown, when | ||
```js | ||
var fut = Future.after(300, null).map(x => x.foo); | ||
fut.forkCatch(e => { | ||
console.error('fatal error:', e.stack); | ||
console.error('caused in: ', e.future.toString()); | ||
process.exit(1); | ||
}, console.error, console.log); | ||
//! fatal error: Cannot read property 'foo' of null | ||
//! at ... | ||
//! caused in: Future.after(300, null).map(x => x.foo) | ||
> forkCatch (log ('fatal error')) | ||
. (log ('rejection')) | ||
. (log ('resolution')) | ||
. (map (x => x.foo) (resolve (null))) | ||
[fatal error]: new Error ("Cannot read property 'foo' of null") | ||
``` | ||
@@ -1365,39 +1122,26 @@ | ||
<details><summary><code>value :: (b -> x) -> Future a b -> Cancel</code></summary> | ||
```hs | ||
value :: (b -> x) -> Future a b -> Cancel | ||
Future.prototype.value :: Future a b ~> (b -> x) -> Cancel | ||
value :: (b -> Any) -> Future a b -> Cancel | ||
``` | ||
</details> | ||
Extracts the value from a resolved Future by forking it. Only use this function | ||
Like [`fork`](#fork) but for the resolution branch only. Only use this function | ||
if you are sure the Future is going to be resolved, for example; after using | ||
[`fold`](#fold). If the Future rejects and `value` was used, an uncatchable | ||
`Error` will be thrown. | ||
[`fold`](#fold). If the Future rejects, `value` will throw an Error. | ||
As with [`fork`](#fork), `value` returns an `unsubscribe` function. See | ||
[Cancellation](#cancellation). | ||
```js | ||
Future.reject(new Error('It broke')) | ||
.fold(S.Left, S.Right) | ||
.value(console.log); | ||
//> Left([Error: It broke]) | ||
> value (log ('resolution')) (resolve (42)) | ||
[resolution]: 42 | ||
``` | ||
As with [`fork`](#fork), `value` returns an `unsubscribe` function. See | ||
[Cancellation](#cancellation). | ||
#### done | ||
<details><summary><code>done :: Nodeback a b -> Future a b -> Cancel</code></summary> | ||
```hs | ||
done :: Nodeback a b -> Future a b -> Cancel | ||
Future.prototype.done :: Future a b ~> Nodeback a b -> Cancel | ||
done :: Nodeback a b -> Future a b -> Cancel | ||
``` | ||
</details> | ||
Run the Future using a [Nodeback](#types) as the continuation. | ||
Fork the Future into a [Nodeback](#types). | ||
This is like [`fork`](#fork), but instead of taking two unary functions, it | ||
@@ -1410,4 +1154,4 @@ takes a single binary function. | ||
```js | ||
Future.of('hello').done((err, val) => console.log(val)); | ||
//> "hello" | ||
> done ((err, val) => log ('resolution') (val)) (resolve (42)) | ||
[resolution]: 42 | ||
``` | ||
@@ -1417,23 +1161,13 @@ | ||
<details><summary><code>promise :: Future a b -> Promise b a</code></summary> | ||
```hs | ||
promise :: Future a b -> Promise b a | ||
Future.prototype.promise :: Future a b ~> Promise b a | ||
promise :: Future a b -> Promise b a | ||
``` | ||
</details> | ||
Run the Future and get a Promise to represent its continuation. | ||
An alternative way to [`fork`](#fork) the Future. Returns a Promise which | ||
resolves with the resolution value, or rejects with the rejection reason of | ||
the Future. | ||
Returns a Promise which resolves with the resolution value, or rejects with | ||
the rejection reason of the Future. | ||
Note that if an exception was encountered during the computation, it will be | ||
thrown and likely not be catchable. | ||
If an exception was encountered during the computation, it will be thrown. | ||
```js | ||
Future.of('Hello').promise().then(console.log); | ||
//> "Hello" | ||
``` | ||
This is a convenience function which provides a "quick and dirty" way to create | ||
@@ -1443,23 +1177,6 @@ a Promise from a Future. You should only use it in scenarios where you're not | ||
exceptions. For example in a test runner that wants you to give it a Promise. | ||
In any other scenario, if you *really* want a Promise, you should probably | ||
make a custom wrapper around [`forkCatch`](#forkcatch) to create your Promise, | ||
for example: | ||
```js | ||
const eventualThing = Future.after(300, 'World'); | ||
new Promise((res, rej) => { | ||
// We've decided that an exception should go to the rejection branch, and | ||
// we're wrapping the failure or success values to not lose information. | ||
const cancel = eventualThing.forkCatch(rej, reason => { | ||
res({success: false, reason: reason, value: null}); | ||
}, value => { | ||
res({success: true, reason: null, value: value}); | ||
}); | ||
// We're also handling cancellation here. | ||
process.on('SIGINT', cancel); | ||
}); | ||
> promise (resolve (42)) .then (log ('resolution')) | ||
[resolution]: 42 | ||
``` | ||
@@ -1471,11 +1188,6 @@ | ||
<details><summary><code>race :: Future a b -> Future a b -> Future a b</code></summary> | ||
```hs | ||
race :: Future a b -> Future a b -> Future a b | ||
Future.prototype.race :: Future a b ~> Future a b -> Future a b | ||
race :: Future a b -> Future a b -> Future a b | ||
``` | ||
</details> | ||
Race two Futures against each other. Creates a new Future which resolves or | ||
@@ -1487,33 +1199,14 @@ rejects with the resolution or rejection value of the first Future to settle. | ||
```js | ||
Future.after(100, 'hello') | ||
.race(Future.after(50, 'bye')) | ||
.fork(console.error, console.log); | ||
//> "bye" | ||
> fork (log ('rejection')) | ||
. (log ('resolution')) | ||
. (race (after (15) ('left')) (after (30) ('right'))) | ||
[resolution]: "left" | ||
``` | ||
With good old `reduce`, we can turn this into a `first` function, where the | ||
resulting Future will be the first to resolve, or the first to reject. | ||
```js | ||
var first = futures => futures.reduce(Future.race, Future.never); | ||
first([ | ||
Future.after(100, 'hello'), | ||
Future.after(50, 'bye'), | ||
Future.rejectAfter(25, 'nope') | ||
]) | ||
.fork(console.error, console.log); | ||
//! "nope" | ||
``` | ||
#### both | ||
<details><summary><code>both :: Future a b -> Future a c -> Future a (Pair b c)</code></summary> | ||
```hs | ||
both :: Future a b -> Future a c -> Future a (Pair b c) | ||
Future.prototype.both :: Future a b ~> Future a c -> Future a (Pair b c) | ||
both :: Future a b -> Future a c -> Future a (Pair b c) | ||
``` | ||
</details> | ||
Run two Futures in parallel and get a [`Pair`](#types) of the results. When | ||
@@ -1524,7 +1217,6 @@ either Future rejects, the other Future will be cancelled and the resulting | ||
```js | ||
var a = Future.of('a'); | ||
var b = Future.of('b'); | ||
Future.both(a, b).fork(console.error, console.log); | ||
//> ['a', 'b'] | ||
> fork (log ('rejection')) | ||
. (log ('resolution')) | ||
. (both (after (15) ('left')) (after (30) ('right'))) | ||
[resolution]: ["left", "right"] | ||
``` | ||
@@ -1534,4 +1226,2 @@ | ||
<details><summary><code>parallel :: PositiveInteger -> Array (Future a b) -> Future a (Array b)</code></summary> | ||
```hs | ||
@@ -1541,41 +1231,35 @@ parallel :: PositiveInteger -> Array (Future a b) -> Future a (Array b) | ||
</details> | ||
Creates a Future which when forked runs all Futures in the given Array in | ||
parallel, ensuring no more than `limit` Futures are running at once. | ||
When one Future rejects, all currently running Futures will be cancelled and | ||
the resulting Future will reject. | ||
In the following example, we're running up to 5 Futures in parallel. Every | ||
Future takes about 20ms to settle, which means the result should appear after | ||
about 40ms. | ||
```js | ||
var tenFutures = Array.from(Array(10).keys()).map(Future.after(20)); | ||
If we use `1` for the limit, the Futures would run in sequence, causing the | ||
result to appear only after 200ms. | ||
//Runs all Futures in sequence: | ||
Future.parallel(1, tenFutures).fork(console.error, console.log); | ||
//after about 200ms: | ||
//> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] | ||
We can also use `Infinity` as the limit. This would create a function similar | ||
to `Promise.all`, which always runs all Futures in parallel. This can easily | ||
cause the computation to consume too many resources, however, so I would | ||
advise using a number roughly equal to maximum size of Array you think your | ||
program should handle. | ||
//Runs upto five Futures in parallel: | ||
Future.parallel(5, tenFutures).fork(console.error, console.log); | ||
//after about 40ms: | ||
//> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] | ||
//Runs all Futures in parallel: | ||
Future.parallel(Infinity, tenFutures).fork(console.error, console.log); | ||
//after about 20ms: | ||
//> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] | ||
```js | ||
> fork (log ('rejection')) | ||
. (log ('resolution')) | ||
. (parallel (5) (Array.from (Array (10) .keys ()) .map (after (20)))) | ||
[resolution]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] | ||
``` | ||
If you want to settle all Futures, even if some may fail, you can use this in | ||
combination with [fold](#fold): | ||
When one Future rejects, all currently running Futures will be cancelled and | ||
the resulting Future will reject. If you want to settle all Futures, even if | ||
some may fail, you can use `parallel` in combination with [fold](#fold). | ||
```js | ||
var unstableFutures = Array.from({length: 4}, (_, i) => | ||
Future.node(done => done(Math.random() > 0.75 ? 'failed' : null, i)) | ||
); | ||
var stabalizedFutures = unstableFutures.map(Future.fold(S.Left, S.Right)); | ||
Future.parallel(Infinity, stabalizedFutures).fork(console.error, console.log); | ||
//> [ Right(0), Left("failed"), Right(2), Right(3) ] | ||
> fork (log ('rejection')) | ||
. (log ('resolution')) | ||
. (parallel (2) ([resolve (42), reject ('It broke!')] | ||
. .map (fold (S.Left) (S.Right)))) | ||
[resolution]: [Right (42), Left ("It broke!")] | ||
``` | ||
@@ -1597,21 +1281,24 @@ | ||
See also [`ap`](#ap) and [`alt`](#alt). | ||
```js | ||
var {of, ap, sequence} = require('sanctuary'); | ||
var {Future, Par, seq} = require('fluture'); | ||
//Some dummy values | ||
var x = 1; | ||
var f = a => a + 1; | ||
const x = 41; | ||
const f = a => a + 1; | ||
//The following two are equal ways to construct a ConcurrentFuture | ||
var parx = of(Par, x); | ||
var parf = Par(of(Future, f)); | ||
const parx = S.of (Par) (x) | ||
const parf = Par (S.of (Future) (f)) | ||
//We can make use of parallel apply | ||
seq(ap(parx, parf)).value(console.log); | ||
//> 2 | ||
value (log ('resolution')) (seq (ap (parx) (parf))) | ||
[resolution]: 42 | ||
//Or concurrent sequencing | ||
seq(sequence(Par, [parx, parf])).value(console.log); | ||
//> [x, f] | ||
//Concurrent sequencing | ||
value (log ('resolution')) (seq (S.sequence (Par) ([parx, parx, parx]))) | ||
[resolution]: [41, 41, 41] | ||
//And concurrent alt | ||
value (log ('resolution')) (alt (after (15) ('left')) (after (30) ('right'))) | ||
[resolution]: "left" | ||
``` | ||
@@ -1621,6 +1308,2 @@ | ||
Converts a Future to a ConcurrentFuture. | ||
<details><summary><code>Par :: Future a b -> ConcurrentFuture a b</code></summary> | ||
```hs | ||
@@ -1630,28 +1313,4 @@ Par :: Future a b -> ConcurrentFuture a b | ||
</details> | ||
Converts a Future to a ConcurrentFuture. | ||
##### Par.of | ||
Constructs a ConcurrentFuture with the given resolution value. | ||
<details><summary><code>Par.of :: b -> ConcurrentFuture a b</code></summary> | ||
```hs | ||
Par.of :: b -> ConcurrentFuture a b | ||
``` | ||
</details> | ||
##### Par.zero | ||
Constructs a ConcurrentFuture which will never resolve or reject with anything. | ||
<details><summary><code>Par.zero :: () -> ConcurrentFuture a a</code></summary> | ||
```hs | ||
Par.zero :: () -> ConcurrentFuture a a | ||
``` | ||
</details> | ||
##### seq | ||
@@ -1661,4 +1320,2 @@ | ||
<details><summary><code>seq :: ConcurrentFuture a b -> Future a b</code></summary> | ||
```hs | ||
@@ -1668,4 +1325,2 @@ seq :: ConcurrentFuture a b -> Future a b | ||
</details> | ||
### Resource management | ||
@@ -1678,4 +1333,2 @@ | ||
<details><summary><code>hook :: Future a b -> (b -> Future c d) -> (b -> Future a e) -> Future a e</code></summary> | ||
```hs | ||
@@ -1685,4 +1338,2 @@ hook :: Future a b -> (b -> Future c d) -> (b -> Future a e) -> Future a e | ||
</details> | ||
Combines resource acquisition, consumption, and disposal in such a way that you | ||
@@ -1692,3 +1343,3 @@ can be sure that a resource will always be disposed if it was acquired, even if | ||
The signature is like `hook(acquire, dispose, consume)`, where: | ||
The signature is like `hook (acquire, dispose, consume)`, where: | ||
@@ -1706,11 +1357,14 @@ - `acquire` is a Future which might create connections, open files, etc. | ||
<!-- eslint-disable no-undef --> | ||
```js | ||
var withConnection = Future.hook( | ||
openConnection('localhost'), | ||
closeConnection | ||
); | ||
> import {open, read, close} from 'fs' | ||
withConnection(conn => query(conn, 'SELECT * FROM users')) | ||
.fork(console.error, console.log); | ||
> const withFile = hook (node (done => open ('package.json', 'r', done))) | ||
. (fd => node (done => close (fd, done))) | ||
> fork (log ('rejection')) | ||
. (log ('resolution')) | ||
. (withFile (fd => node (done => ( | ||
. read (fd, Buffer.alloc (1), 0, 1, null, (e, _, x) => done (e, x))) | ||
. ))) | ||
[resolution]: <Buffer 7b> | ||
``` | ||
@@ -1730,4 +1384,2 @@ | ||
<details><summary><code>pipe :: Future a b ~> (Future a b -> c) -> c</code></summary> | ||
```hs | ||
@@ -1737,16 +1389,14 @@ Future.prototype.pipe :: Future a b ~> (Future a b -> c) -> c | ||
</details> | ||
A method available on all Futures to allow arbitrary functions over Futures to | ||
be included in a fluent-style method chain. | ||
This method is particularly useful in combination with functions derived from | ||
Fantasy Land implementations, for example [`S.join`][S:join]: | ||
You can think of this as a fallback for the [ESNext pipe operator (`|>`)][2]. | ||
```js | ||
Future.of(42) | ||
.map(Future.resolve) | ||
.pipe(S.join) | ||
.value(console.log); | ||
//> 42 | ||
> resolve (x => y => x * y) | ||
. .pipe (ap (after (20) (Math.PI))) | ||
. .pipe (ap (after (20) (13.37))) | ||
. .pipe (map (Math.round)) | ||
. .pipe (fork (log ('rejection')) (log ('resolution'))) | ||
[resolution]: 42 | ||
``` | ||
@@ -1756,4 +1406,2 @@ | ||
<details><summary><code>cache :: Future a b -> Future a b</code></summary> | ||
```hs | ||
@@ -1763,4 +1411,2 @@ cache :: Future a b -> Future a b | ||
</details> | ||
Returns a Future which caches the resolution value or rejection reason of the | ||
@@ -1775,21 +1421,35 @@ given Future so that whenever it's forked, it can load the value from cache | ||
There is a glaring drawback to using `cache`, which is that returned Futures | ||
are no longer referentially transparent, making reasoning about them more | ||
difficult and refactoring code that uses them harder. | ||
**There is a glaring drawback to using `cache`**, which is that returned | ||
Futures are no longer referentially transparent, making reasoning about them | ||
more difficult and refactoring code that uses them harder. | ||
```js | ||
var {readFile} = require('fs'); | ||
var eventualPackage = Future.cache( | ||
Future.node(done => { | ||
console.log('Reading some big data'); | ||
readFile('package.json', 'utf8', done); | ||
}) | ||
); | ||
> import {readFile} from 'fs' | ||
eventualPackage.fork(console.error, console.log); | ||
//> "Reading some big data" | ||
//> "{...}" | ||
> const eventualPackageName = ( | ||
. node (done => readFile ('package.json', 'utf8', done)) | ||
. .pipe (chain (encase (JSON.parse))) | ||
. .pipe (chain (encase (x => x.name))) | ||
. .pipe (map (data => { | ||
. log ('debug') ('Read, parsed, and traversed the package data') | ||
. return data | ||
. })) | ||
. ) | ||
eventualPackage.fork(console.error, console.log); | ||
//> "{...}" | ||
> fork (log ('rejection')) (log ('resolution')) (eventualPackageName) | ||
[debug]: "Read, parsed, and traversed the package data" | ||
[resolution]: "Fluture" | ||
> fork (log ('rejection')) (log ('resolution')) (eventualPackageName) | ||
[debug]: "Read, parsed, and traversed the package data" | ||
[resolution]: "Fluture" | ||
> const eventualCachedPackageName = cache (eventualPackageName) | ||
> fork (log ('rejection')) (log ('resolution')) (eventualCachedPackageName) | ||
[debug]: "Read, parsed, and traversed the package data" | ||
[resolution]: "Fluture" | ||
> fork (log ('rejection')) (log ('resolution')) (eventualCachedPackageName) | ||
[resolution]: "Fluture" | ||
``` | ||
@@ -1799,4 +1459,2 @@ | ||
<details><summary><code>isFuture :: a -> Boolean</code></summary> | ||
```hs | ||
@@ -1806,4 +1464,2 @@ isFuture :: a -> Boolean | ||
</details> | ||
Returns true for [Futures](#types) and false for everything else. This function | ||
@@ -1815,15 +1471,8 @@ (and [`S.is`][S:is]) also return `true` for instances of Future that were | ||
<!-- eslint-disable no-unused-expressions --> | ||
```js | ||
var Future1 = require('/path/to/fluture'); | ||
var Future2 = require('/other/path/to/fluture'); | ||
var noop = () => {}; | ||
> isFuture (resolve (42)) | ||
true | ||
var m1 = Future1(noop); | ||
Future1.isFuture(m1) === (m1 instanceof Future1); | ||
//> true | ||
var m2 = Future2(noop); | ||
Future1.isFuture(m2) === (m2 instanceof Future1); | ||
//> false | ||
> isFuture (42) | ||
false | ||
``` | ||
@@ -1833,10 +1482,6 @@ | ||
<details><summary><code>never :: Future a a</code></summary> | ||
```hs | ||
never :: Future a a | ||
never :: Future a b | ||
``` | ||
</details> | ||
A Future that never settles. Can be useful as an initial value when reducing | ||
@@ -1847,4 +1492,2 @@ with [`race`](#race), for example. | ||
<details><summary><code>isNever :: a -> Boolean</code></summary> | ||
```hs | ||
@@ -1854,4 +1497,2 @@ isNever :: a -> Boolean | ||
</details> | ||
Returns `true` if the given input is a `never`. | ||
@@ -1861,11 +1502,6 @@ | ||
<details><summary><code>extractLeft :: Future a b -> Array a</code></summary> | ||
```hs | ||
extractLeft :: Future a b -> Array a | ||
Future.prototype.extractLeft :: Future a b ~> () -> Array a | ||
extractLeft :: Future a b -> Array a | ||
``` | ||
</details> | ||
Returns an array whose only element is the rejection reason of the Future. | ||
@@ -1878,11 +1514,6 @@ In many cases it will be impossible to extract this value; In those cases, the | ||
<details><summary><code>extractRight :: Future a b -> Array b</code></summary> | ||
```hs | ||
extractRight :: Future a b -> Array b | ||
Future.prototype.extractRight :: Future a b ~> () -> Array b | ||
extractRight :: Future a b -> Array b | ||
``` | ||
</details> | ||
Returns an array whose only element is the resolution value of the Future. | ||
@@ -1895,4 +1526,2 @@ In many cases it will be impossible to extract this value; In those cases, the | ||
<details><summary><code>debugMode :: Boolean -> Undefined</code></summary> | ||
```hs | ||
@@ -1902,4 +1531,2 @@ debugMode :: Boolean -> Undefined | ||
</details> | ||
Enable or disable Fluture's debug mode. Debug mode is disabled by default. | ||
@@ -1909,3 +1536,3 @@ Pass `true` to enable, or `false` to disable. | ||
```js | ||
Future.debugMode(true); | ||
debugMode (true) | ||
``` | ||
@@ -1918,3 +1545,3 @@ | ||
```hs | ||
context :: Future a b ~> List Context | ||
Future.prototype.context :: Future a b ~> List Context | ||
``` | ||
@@ -1927,15 +1554,4 @@ | ||
stacktraces leading up to the creation of the `Future` instance. They are used | ||
by Fluture to generate asynchronous stack traces. | ||
by Fluture to generate contextual stack traces. | ||
```js | ||
Future.debugMode(true); | ||
const future = Future.after(10, 'Hello'); | ||
let context = future.context; | ||
while(context.head){ | ||
console.log(context.head.stack); | ||
context = context.tail; | ||
} | ||
``` | ||
## License | ||
@@ -1984,7 +1600,7 @@ | ||
[1]: https://en.wikipedia.org/wiki/Continuation-passing_style | ||
[2]: https://github.com/tc39/proposal-pipeline-operator | ||
[3]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#iterator | ||
[5]: https://vimeo.com/106008027 | ||
[6]: https://github.com/rpominov/static-land | ||
[7]: https://promisesaplus.com/ | ||
[9]: https://wearereasonablepeople.nl/ | ||
[10]: https://medium.com/@avaq/broken-promises-2ae92780f33 |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
22
168945
55
3197
1
1515