/** * A Promise whose incoming value can be hot swapped. * @typeParam T The type of the value that the promise will resolve to. * * @remarks * Can be constructed like a Promise, or from an existing Promise. */ export class Future extends Promise { private fate: Promise | undefined private resolve: (value: T) => void private reject: (reason?: any) => void public done = false public constructor( executor: | Promise | ((resolve: (value: T) => void, reject: (reason?: any) => void) => void), ) { let superResolve: ((value: T) => void) | undefined let superReject: ((reason?: any) => void) | undefined super((resolve, reject) => { superResolve = resolve superReject = reject }) this.resolve = superResolve as (value: T) => void this.reject = superReject as (reason?: any) => void this.use(executor instanceof Promise ? executor : new Promise(executor)) } private pass(promise: Promise, value: T) { if (promise === this.fate) { this.resolve(value) this.done = true } } private fail(promise: Promise, reason: any) { if (promise === this.fate) { this.reject(reason) this.done = true } } public use(value: Promise | T): void { if (this === value) { return } if (value instanceof Promise) { const promise = value this.fate = promise promise.then( (resolved) => { this.pass(promise, resolved) }, (reason) => { this.fail(promise, reason) }, ) } else { this.resolve(value) this.fate = undefined } } }