/** * A Future is a primitive for managing asynchronous side-effects in an * organized manner. * * It works by queuing up the async tasks in a monad like chain, only executing * them when the instruction to do so is given. This is in contrast to the * Promise which executes these side-effects as soon as it is created. A Future * is easier to reason about than a Promise and allows async code to be more * composable. To allow Futures to benefit from the JS engine's built in Promise * support however, Futures also implement the Promise api. */ import { Type } from '../../data/type'; import { Milliseconds } from '../time'; import { Err, Except } from '../error'; import { Monad } from './'; /** * Yield is a value that may be itself or may be wrapped in a [[Future]]. * * This is type is used to represent return values of functions that may be * async or not for situations where it may be desirable to have the. Care * should be used when handling these values as it is easy to forget to fork() * the Future resulting in incorrect values being passed around. * * Use the [[wrap]] before attempting to process a Yield to be on the safe side. */ export type Yield = T | Future; /** * OnError callback function type. */ export type OnError = (e: Error) => void; /** * OnSuccess callback function type. */ export type OnSuccess = (a: A) => void; /** * Aborter callback function type. */ export type Aborter = () => void; /** * ErrorHandler callback function type. * * These are used to trap and recover from errors. */ export type ErrorHandler = (e: Error) => Future; /** * Finalizer callback function type. * * Finalizers can be used to clean up resources etc. */ export type Finalizer = () => Future; /** * NodeFunction is a node platform async function. */ export type NodeFunction = (f: (cb: Callback) => void) => void; /** * Task is the type of functions that execute async work via a Promise. */ export type Task = () => Promise; /** * Callback in node platform style for asynchronous effects. */ export type Callback = (e: Error | undefined | null, a?: A) => void; /** * CallBackReceiver type takes a node style callback * and performs some side-effect. */ export type CallbackReceiver = (cb: Callback) => void; /** * Reducer function type. */ export type Reducer = (p: B, c: A, i: number) => Future; /** * FutureFunc function type. */ export type FutureFunc = (a: A) => Future; /** * ResolveFunc for promises. */ export type ResolveFunc = ((value: A) => TResult1 | PromiseLike) | undefined | null; /** * RejectFunc for promises. */ export type RejectFunc = ((reason: any) => TResult2 | PromiseLike) | undefined | null; /** * CatchFunc */ export type CatchFunc = (reason: any) => A | PromiseLike; /** * Future represents a chain of asynchronous tasks that some result when * executed. * * The Future implementation is different that a Promise as it does not * execute it's tasks until instructed to giving control back to the calling * code (unlike Promises). To accomplish this, a state machine is built up * from the various calls to chain(), map() etc and executed in the run() * method. * * To make using this API easier, doFuture() is provided which allows chains * of Futures to be created without callback hell via generators. Use the run() * method to get a Promise that contains the final value or treat the future * itself as a Promise (calling then() also executes the Future). * * @typeParam A - The type of the final value. */ export declare abstract class Future implements Monad, Promise { tag: string; /** * @param tag - Used internally to distinguish Future types. */ constructor(tag?: string); /** * of wraps a pure value in a Future. */ static of(a: A): Future; /** * do notation for Futures using async functions. * * An async function executes its body sequentially, pausing at each 'await' * statement preventing asynchronous tasks from pre-empting each other. This * is in line with how Futures are meant to work and could be seen as the * Promise equivalent of: * * ``` * pure().chain(task1).chain(task2).chain(task3); * ``` * The difference between Futures and promises of course, is that Futures do * not execute their tasks until fork() is called whereas Promises are * immediate. Nonetheless, an async function can be treated as a Future * because it does not execute any code until it is called. * * This static method may therfore be more desirable than doFuture() as it * allows for the use of arrow functions doing await with the need to set * `this` to a variable. */ static do(fun: Task): Future; /** * raise wraps an Error in a Future. * * This future will be considered a failure. */ static raise: (e: Err) => Future; /** * fromCallback produces a Future from a node style async function. */ static fromCallback: (f: CallbackReceiver) => Future; /** * parallel runs a list of Futures in parallel failing if any * fail and succeeding with a list of successful values. */ static parallel: (list: Future[]) => Future; /** * sequential execution of a list of futures. * * This function succeeds with a list of all results or fails on the first * error. */ static sequential: (list: Future[]) => Future; /** * batch runs a list of batched Futures one batch at a time. */ static batch: (list: Future[][]) => Future; /** * reduce a list of values into a single value using a reducer function that * produces a Future. */ static reduce: (list: A_1[], initValue: B, f: Reducer) => Future; /** * race given a list of Futures, will return a Future that is settled by * the first error or success to occur. * * Raising an error if the list is empty. */ static race: (list: Future[]) => Future; /** * some executes a list of Futures sequentially until one resolves with a * successful value. * * If none resolve successfully, the final error is raised. */ static some: (list: Future[]) => Future; /** * liftSync wraps a synchronous function in a Future. */ static liftSync: (f: () => A_1) => Future; get [Symbol.toStringTag](): string; of(a: A): Future; map(f: (a: A) => B): Future; ap(ft: Future<(a: A) => B>): Future; chain(f: (a: A) => Future): Future; trap(f: (e: Error) => Future): Future; finish(f: () => Future): Future; then(onResolve?: ResolveFunc, onReject?: RejectFunc): Promise; catch(f: CatchFunc | undefined | null): Promise; finally(f: () => void | undefined | null): Promise; /** * fork triggers the asynchronous execution of the Future passing the * result or error to the provided callbacks. */ fork(onError?: OnError, onSuccess?: OnSuccess): void; /** * run this Future triggering execution of its asynchronous work. */ run(): Promise; } /** * Pure constructor. */ export declare class Pure extends Future { value: A; constructor(value: A); map(f: (a: A) => B): Future; ap(ft: Future<(a: A) => B>): Future; } /** * Bind constructor. * @internal */ export declare class Bind extends Future { target: Future; func: (a: A) => Future; constructor(target: Future, func: (a: A) => Future); } /** * Call constructor. * @internal */ export declare class Call extends Future { target: (a: A) => Future; constructor(target: (a: A) => Future); } /** * Catch constructor. * @internal */ export declare class Catch extends Future { target: Future; func: (e: Error) => Future; constructor(target: Future, func: (e: Error) => Future); } /** * Finally constructor. * @internal */ export declare class Finally extends Future { target: Future; func: () => Future; constructor(target: Future, func: () => Future); } /** * Trap constructor. * @internal */ export declare class Trap extends Future { func: (e: Error) => Future; constructor(func: (e: Error) => Future); } /** * Raise constructor. */ export declare class Raise extends Future { value: Err; constructor(value: Err); map(_: (a: A) => B): Future; ap(_: Future<(a: A) => B>): Future; chain(_: (a: A) => Future): Future; } /** * Run constructor. * @internal */ export declare class Run extends Future { task: Task; constructor(task: Task); } /** * Generation constructor. * * @internal */ export declare class Generation extends Future { src: Generator, Future, Type>; constructor(src: Generator, Future, Type>); } /** * @internal */ export declare class Tag { index: number; value: A; constructor(index: number, value: A); } /** * voidPure is a Future that provides the absence of a value for your * convenience. */ export declare const voidPure: Future; /** * wrap a value in a Future returning the value if the value is itself a Future. */ export declare const wrap: (a: A | Future) => Future; /** * run sets up an async task to be executed at a later point. */ export declare const run: (task: Task) => Future; export { run as liftP }; /** * delay execution of a function f after n milliseconds have passed. * * Any errors thrown are caught and processed in the Future chain. */ export declare const delay: (f: () => A, n?: Milliseconds) => Future; /** * wait n milliseconds before continuing the Future chain. */ export declare const wait: (n?: Milliseconds) => Future; export declare const pure: typeof Future.of; export declare const fromCallback: (f: CallbackReceiver) => Future; export declare const parallel: (list: Future[]) => Future; export declare const sequential: (list: Future[]) => Future; export declare const batch: (list: Future[][]) => Future; export declare const reduce: (list: A[], initValue: B, f: Reducer) => Future; export declare const race: (list: Future[]) => Future; export declare const some: (list: Future[]) => Future; export declare const raise: (e: Err) => Future; export declare const attempt: (f: () => A) => Future; /** * toPromise transforms a Future into a Promise. * * This function depends on the global promise constructor and * will fail if the environment does not provide one. * * @deprecated */ export declare const toPromise: (ft: Future) => Promise; /** * fromExcept converts an Except to a Future. */ export declare const fromExcept: (e: Except) => Future; /** * @internal * TODO: Remove Type usage. */ export type DoFutureGenerator = () => Generator, Future, Type>; /** * doFuture allows for multiple Futures to be chained together in an almost * monadic fashion via a generator function. * * Each Future yielded from the generator is executed sequentially with results * made available via the Generator#next() method. Raise values trigger an * internal error handling mechanism and can be caught via try/catch clauses * in the generator. * * Note: due to the lazy nature of how Futures are evaluated, try/catch will not * intercept a Raise used with a return statement. At that point the generator * is already complete and that Raise must be handled by the calling code if * desired. Alternatively, you can yield the final Future instead of returning * it. That way it can be intercepted by the try/catch. * * @deprecated */ export declare const doFuture: (f: DoFutureGenerator) => Future;