inventoresed
Version:
Z-Wave driver written entirely in JavaScript/TypeScript
62 lines (52 loc) • 1.82 kB
text/typescript
import {
createDeferredPromise,
DeferredPromise,
} from "alcalzone-shared/deferred-promise";
/** Allows waiting for something for a given amount of time, after which the expectation will automatically be rejected. */
export class TimedExpectation<TResult = void, TPredicate = never>
implements PromiseLike<TResult>
{
public constructor(
timeoutMs: number,
public readonly predicate?: (input: TPredicate) => boolean,
private readonly timeoutErrorMessage: string = "Expectation was not fulfilled within the timeout",
) {
this.promise = createDeferredPromise<TResult>();
this.timeout = setTimeout(() => this.reject(), timeoutMs);
// We need create the stack on a temporary object or the Error
// class will try to print the message
const tmp = { message: "" };
Error.captureStackTrace(tmp, TimedExpectation);
this.stack = (tmp as any).stack.replace(/^Error:?\s*\n/, "");
}
private promise: DeferredPromise<TResult>;
private timeout?: NodeJS.Timeout;
private _done: boolean = false;
/** The stack trace where the timed expectation was created */
public readonly stack: string;
public resolve(result: TResult): void {
if (this._done) return;
if (this.timeout) {
clearTimeout(this.timeout);
}
this.promise.resolve(result);
}
private reject(): void {
if (this._done) return;
if (this.timeout) {
clearTimeout(this.timeout);
}
const err = new Error(this.timeoutErrorMessage);
err.stack = this.stack;
this.promise.reject(err);
}
// Make this await-able
then<TResult1 = TResult, TResult2 = never>(
onfulfilled?:
| ((value: TResult) => TResult1 | PromiseLike<TResult1>)
| null,
onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null,
): PromiseLike<TResult1 | TResult2> {
return this.promise.then(onfulfilled, onrejected);
}
}