already
Advanced tools
Comparing version 3.3.0 to 3.4.0
@@ -177,2 +177,32 @@ declare const _default: { | ||
export declare function rethrow<T extends Error = any>(fn: (err?: T) => (void | PromiseLike<void>)): (err: T) => Promise<never>; | ||
export interface NotTimedOutValue<T> { | ||
timedout: false; | ||
reflection: Reflection<T>; | ||
promise: Promise<T>; | ||
} | ||
export interface TimedOutValue<T> { | ||
timedout: true; | ||
reflection: undefined; | ||
promise: Promise<T>; | ||
} | ||
/** | ||
* A TimeoutValue contains: | ||
* * A boolean whether the promise timed out | ||
* * The synchronous value or error of a resolved or rejected promise (if | ||
* not timed out) | ||
* * The promise itself to further await if timed out. | ||
*/ | ||
export declare type TimeoutValue<T> = NotTimedOutValue<T> | TimedOutValue<T>; | ||
/** | ||
* Timeout a promise with a certain number of milliseconds. | ||
* | ||
* Returns a promise (that will never be rejected) being resolved within _at | ||
* least_ the timeout duration. The returned value contains the promise | ||
* value or error, unless timeout was reached. | ||
* | ||
* @param promise The promise to await for at most <timeout> ms | ||
* @param timeout Milliseconds to wait at most before timing out | ||
* @returns A promise to a {@link TimeoutValue} object | ||
*/ | ||
export declare function timeout<T>(promise: Promise<T>, timeout: number): Promise<TimeoutValue<T>>; | ||
export declare function wrapFunction<R extends void>(wrap: () => () => R): (<U extends void, V extends Promise<U> | U>(cb: () => V) => V) & (<U extends any, V extends Promise<U> | U>(cb: () => V) => V); | ||
@@ -179,0 +209,0 @@ export declare function wrapFunction<T extends {}, R extends void>(wrap: (t: T) => () => R): (<U extends void, V extends Promise<U> | U>(t: T, cb: () => V) => V) & (<U extends any, V extends Promise<U> | U>(t: T, cb: () => V) => V); |
@@ -469,2 +469,27 @@ export default { | ||
} | ||
/** | ||
* Timeout a promise with a certain number of milliseconds. | ||
* | ||
* Returns a promise (that will never be rejected) being resolved within _at | ||
* least_ the timeout duration. The returned value contains the promise | ||
* value or error, unless timeout was reached. | ||
* | ||
* @param promise The promise to await for at most <timeout> ms | ||
* @param timeout Milliseconds to wait at most before timing out | ||
* @returns A promise to a {@link TimeoutValue} object | ||
*/ | ||
export async function timeout(promise, timeout) { | ||
const sentry = Symbol(); | ||
return Promise.race([reflect(promise), delay(timeout, sentry)]) | ||
.then((value) => { | ||
if (value === sentry) { | ||
// Timed out | ||
return { timedout: true, promise, reflection: undefined }; | ||
} | ||
else { | ||
// Did not time out, the value is the resolved reflection | ||
return { timedout: false, promise, reflection: value }; | ||
} | ||
}); | ||
} | ||
export function wrapFunction(wrap) { | ||
@@ -471,0 +496,0 @@ // tslint:disable-next-line |
@@ -5,3 +5,3 @@ { | ||
"license": "MIT", | ||
"version": "3.3.0", | ||
"version": "3.4.0", | ||
"author": "Gustaf Räntilä <g.rantila@gmail.com>", | ||
@@ -8,0 +8,0 @@ "repository": { |
@@ -69,2 +69,4 @@ [![npm version][npm-image]][npm-url] | ||
<br> Ensure a callback re-throws (to not silently swallow errors) | ||
* [timeout](#timeout) | ||
<br> Timeout a promise (race it against a timer) | ||
* [wrapFunction](#wrapfunction) | ||
@@ -650,3 +652,15 @@ <br> Wrap a function with a potentially asynchronous prolog and/or epilog (e.g. init/cleanup) | ||
The `Reflection` type has the form: | ||
```ts | ||
interface Reflection< T > | ||
{ | ||
error?: Error; | ||
value?: T; | ||
isResolved: boolean; | ||
isRejected: boolean; | ||
} | ||
``` | ||
## inspect | ||
@@ -754,2 +768,48 @@ | ||
## timeout | ||
To race a promise against a timer (to run code within a certain timeframe), use `timeout`. It is basically a `Promise.race()` against a [`delay()`](#delay), with a nice API. The first argument is the promise to race, and the second is the number of milliseconds to wait for at most. | ||
The promise returned from `timeout()` will never be rejected. It will be resolved within the timeout period. | ||
The value of the returned promise is an object on the form: | ||
```ts | ||
interface TimeoutValue< T > | ||
{ | ||
timedout: boolean; | ||
reflection?: Reflection< T >; // If the promise did NOT timeout | ||
promise: Promise< T >; | ||
} | ||
``` | ||
Code can check if `timedout` is true or false. If it's true, the `promise` property can be used to further wait for the completion (at least a `catch` should be registered to handle errors). If `timedout` is false, the `reflection` property is of type [`Reflection`](#reflect) and contains the value or error. | ||
```ts | ||
import { timeout } from 'already' | ||
const { timedout, reflection, promise } = await timeout( somePromise, 3000 ); | ||
if ( timedout ) | ||
{ | ||
// The promise timed out | ||
promise.catch( err => | ||
console.error( `Timed out promise eventually failed`, err.stack ) | ||
); | ||
} | ||
else | ||
{ | ||
// The promise was resolved or rejected | ||
if ( reflection.isResolved ) | ||
{ | ||
doSomething( reflection.value ); | ||
} | ||
else | ||
{ | ||
handleError( reflection.error ); | ||
} | ||
} | ||
``` | ||
## wrapFunction | ||
@@ -756,0 +816,0 @@ |
76701
945
1035