Created
February 19, 2024 21:16
Revisions
-
SamJakob created this gist
Feb 19, 2024 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,86 @@ /** * This is a TypeScript version of the `Completer` class from Dart. * * A `Completer` provides a future that can be imperatively concluded (once and * only once) with either `#complete` or `#completeError`. * Once the completer has completed (or errored), the future will be resolved * with the specified value. * * This is trivially implemented by instantiating a Promise and capturing the * resolve and reject functions. */ export class Completer<T> { readonly #promise: Promise<T>; #resolve: (value: (T | PromiseLike<T>)) => void; #reject: (reason?: any) => void; #completed = false; /** * Initialize a {@link Completer}. * * A Completer provides a future that can be imperatively concluded (once) * with either {@link #complete} or {@link #completeError}. Once the * completer has completed (or errored), the future will be resolved with * the specified value. It will then not be possible to complete the * completer again (as it will throw an error if an attempt is made to do * so). */ public constructor() { // Initialize #resolve and #reject with a function that throws an error // so errors are not silently swallowed if the completer is not // initialized properly. const failedInitialize = () => { throw new Error("Completer failed to initialize"); }; this.#resolve = failedInitialize; this.#reject = failedInitialize; // Initialize the #promise property with a new promise and define the // #resolve and #reject functions to be the resolve and reject functions // of the promise. this.#promise = new Promise((resolve, reject) => { this.#resolve = resolve; this.#reject = reject; }); } /** * Returns the promise that can be used to observe the completion of the * completer. */ public get promise(): Promise<T> { return this.#promise; } /** * Returns true if either {@link #complete} or {@link #completeError} has * been called on the completer. */ public get completed(): boolean { return this.#completed; } /** * Complete the completer with the specified value. * @param value The value to complete the completer with. */ public complete(value: T) { if (this.#completed) { throw new Error("Completer has already completed"); } this.#completed = true; this.#resolve(value); } /** * Complete the completer with the specified error. * @param error The error to complete the completer with. */ public completeError(error: any) { if (this.#completed) { throw new Error("Completer has already completed"); } this.#completed = true; this.#reject(error); } }