type FutureResolveFunction = (err: Error, val: T) => void; type FutureOrFutureArray = Future | Array>; // In the future we can use this to extend the type of FutureObject if typescript // support for dynamic types improves // https://stackoverflow.com/questions/44323441/changing-property-name-in-typescript-mapped-type // type FutureObjectFunctions = {[K in keyof O]: O[K] extends ((...args: infer P) => infer R) ? // (...args: P) => Future : never}; // // type FutureObjectProperties = {[K in keyof O]: O[K] extends (...args: any[]) => any ? never: O[K]}; declare global { type FutureObject = T & any; type FutureFunction = (...args: any[]) => Future; interface Function { /** * Returns a future-function which, when run, starts running the target * function and returns a future for the result. * * Example usage: * var funcy = function(arg) { * return arg+1; * }.future(); * * funcy(1).wait(); // returns 2 */ future(detach?: boolean): FutureFunction; } } interface FutureConstructor { new(): Future; /** * Wrap a node-style async function to return a future in place of using a callback. * A node-style async function is usually in the form (...args: any, cb: (err?: Error, ...cbArgs: any) => any) => any * * If a single function is passed, a future-returning function is created. If an object is passed a * new object is returned with all functions wrapped. * * The value that is returned from the invocation of the underlying function is assigned to the * property `_` on the future. This is useful for functions like `execFile` which take a callback, * but also return meaningful information. * * @param fnOrObject - the function or object to wrap * @param multi - indicates that this callback will return more than 1 argument after `err`. For example, * `child_process.exec()` returns [err, stdout, stderr] * @param suffix - appends a string to every method that was overridden. * If you passed an object. Default is 'Future'. * * Example usage: Future.wrap(asyncFunction)(arg1).wait() */ wrap(fnOrObject: (...args: any[]) => T, multi?: boolean, suffix?: string): FutureFunction; wrap(fnOrObject: O, multi?: boolean, suffix?: string): FutureObject; // wrap(fnOrObject: O, multi?: boolean, suffix?: string): FutureObject & FunctionProperties; /** * Invoke a function(s) that will be run in its own fiber context and return a future to its return * value. * * @description Run a function(s) in a future context, and return a future to their return value. This is useful * for instances where you want a closure to be able to `.wait()`. This also lets you wait for * mulitple parallel opertions to run. * * Example: * Future.task(function() { * // You can safely `wait` on stuff here * }).detach(); */ task(fn: (...args: any[]) => T): Future; task(fn1: Function, fn2: Function, ...fns: Function[]): Future; /** * Wait on a series of futures and then return. If the futures throw an exception this function * /won't/ throw it back. You can get the value of the future by calling get() on it directly. If * you want to wait on a single future you're better off calling future.wait() on the instance. * * Example usage: Future.wait(aFuture, anotherFuture) */ wait(...futures: FutureOrFutureArray[]): void; /** * Support for converting a Future to and from ES6 Promises. * @see Future#promise */ fromPromise(promise: Promise): Future; } interface Future { /** * Return the value of this future. If the future hasn't resolved yet this will throw an error. */ get(): T; /** * Differs from its functional counterpart in that it actually resolves the future. Thus if the * future threw, future.wait() will throw. * * @see get */ wait(): T; /** * Mark this future as returned. All pending callbacks will be invoked immediately. * * value - the value to return when get() or wait() is called. * * Example usage: aFuture.return(value) */ return(value?: T): void; /** * Throw from this future as returned. All pending callbacks will be invoked immediately. * Note that execution will continue normally after running this method, * so make sure you exit appropriately after running throw() * * error - the error to throw when get() or wait() is called. * * Example usage: aFuture.throw(new Error("Something borked")) */ throw(err: Error): void; /** * "detach" this future. Basically this is useful if you want to run a task in a future, you * aren't interested in its return value, but if it throws you don't want the exception to be * lost. If this fiber throws, an exception will be thrown to the event loop and node will * probably fall down. */ detach(): void; /** * Returns whether or not this future has resolved yet. */ isResolved(): boolean; /** * Returns a node-style function which will mark this future as resolved when called. * * Example usage: * var errback = aFuture.resolver(); * asyncFunction(arg1, arg2, etc, errback) * var result = aFuture.wait(); */ resolver(): FutureResolveFunction; /** * Waits for this future to resolve and then invokes a callback. * * If only one argument is passed it is a standard function(err, val){} errback. * * If two arguments are passed, the first argument is a future which will be thrown to in the case * of error, and the second is a function(val){} callback. */ resolve(errback: FutureResolveFunction): this; resolve(future: Future, callback: (val: T) => void): this; /** * Resolve only in the case of success */ resolveSuccess(cb: (val: T) => void): this; /** * Propogate results to another future. * * Example usage: future1.proxy(future2) // future2 gets automatically resolved with however future1 resolves */ proxy(future: Future): void; /** * Propogate only errors to an another future or array of futures. */ proxyErrors(futures: FutureOrFutureArray): this; /** * Support for converting a Future to and from ES6 Promises. * @see FutureConstructor#fromPromise */ promise(): Promise; } declare const Future: FutureConstructor; export = Future;