Last active
March 7, 2024 03:31
-
-
Save pjlsergeant/4afc3c78a8abd1e4e0862b414f5fdb77 to your computer and use it in GitHub Desktop.
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 characters
/* | |
# Why | |
Asynchronously instantiate a singleton only once, even if many calls are made, | |
eg, a handler that lazy-loads a resource, but might be called several times | |
before it's ready. | |
# Synopsis | |
const once = new AwaitOnce<string>(); | |
// Only the first call to run() is executed, the other calls just wait | |
// until that's resolved, and return the initially returned result | |
const p1 = once.run( () => delay('slow', 1000) ) ); | |
const p2 = once.run( () => delay('fast', 100) ) ); | |
const p3 = once.run( () => delay('faster', 10) ) ); | |
const results = await Promise.all( promises ); | |
expect( results ).toEqual(['slow', 'slow', 'slow']); | |
*/ | |
export class AwaitOnce<T> { | |
#promise: Promise<T>; | |
#running: boolean = false; | |
#resolve!: (value: T | PromiseLike<T>) => void; | |
#reject!: (reason?: any) => void; | |
constructor() { | |
this.#promise = new Promise<T>( (resolve, reject) => { | |
this.#resolve = resolve; | |
this.#reject = reject; | |
}); | |
} | |
run( fn: () => Promise<T> ) { | |
if ( ! this.#running ) { | |
this.#running = true; | |
fn().then( this.#resolve ).catch( this.#reject ); | |
} | |
return this.#promise; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment