All files / owid-grapher/clientUtils PromiseCache.ts

100% Statements 38/38
100% Branches 5/5
100% Functions 3/3
100% Lines 38/38

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 371x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 2x 1x 1x 1x 1x 1x 1x 3x 3x 3x 1x 1x 2x 2x 1x 1x 2x 2x 1x 1x
/**
 * Prevents creating multiple promises for a single key.
 *
 * If an existing promise for a key is pending, that promise will be returned without
 * creating a new one.
 *
 * If a promise throws an error, it will be discarded, and a new one created the next
 * time a key is requested.
 *
 * For now it only supports primitive value keys, but we can extend it if necessary.
 */
export class PromiseCache<Key extends string | number | undefined, Result> {
    constructor(private createPromiseFromKey: (key: Key) => Promise<Result>) {}
 
    private promisesByKey = new Map<Key, Promise<Result>>()
 
    get(key: Key): Promise<Result> {
        if (!this.promisesByKey.has(key)) {
            this.promisesByKey.set(
                key,
                // Make sure to attach .catch() _before_ adding it to the cache.
                // Otherwise external logic would be able to attach a catch() that
                // could make this one unreachable.
                this.createPromiseFromKey(key).catch((error) => {
                    this.promisesByKey.delete(key)
                    throw error
                })
            )
        }
        return this.promisesByKey.get(key)!
    }
 
    has(key: Key): boolean {
        return this.promisesByKey.has(key)
    }
}