export class PromiseHolder { public liberatedAt?: number; private _promise: Promise; private _resolveFn: (value: T | PromiseLike) => void; private _rejectFn: (reason?: any) => void; public get isLiberated(): boolean { return !!this.liberatedAt; } constructor() { this._promise = new Promise((resolve, reject) => { this._resolveFn = resolve; this._rejectFn = reject; }); } public getPromise(): Promise { return this._promise; } public get promise(): Promise { return this._promise; } public resolve(value: T | PromiseLike): void { if (this.isLiberated) { throw new Error( 'Cannot resolve a PromiseHolder that has already been liberated.', ); } this.liberatedAt = Date.now(); this._resolveFn(value); } public reject(reason?: Error): void { if (this.isLiberated) { throw new Error( 'Cannot reject a PromiseHolder that has already been liberated.', ); } this.liberatedAt = Date.now(); this._rejectFn(reason); } }