ext/vscode/src/utils/lazy.ts (57 lines of code) (raw):

// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. export class Lazy<T> { private isValueCreated: boolean = false; private val: T | undefined; public constructor(private readonly valueFactory: () => T) { } public get hasValue(): boolean { return this.isValueCreated; } public clear(): void { this.isValueCreated = false; } public get value(): T { if (this.isValueCreated) { return this.val as T; } this.val = this.valueFactory(); this.isValueCreated = true; return this.val; } } export class AsyncLazy<T> { private isValueCreated: boolean = false; private val: T | undefined; private valuePromise: Promise<T> | undefined; // eslint-disable-next-line @typescript-eslint/naming-convention public constructor(private readonly valueFactory: () => Promise<T>, private valueLifetime?: number) { } public get hasValue(): boolean { return this.isValueCreated; } public clear(): void { this.isValueCreated = false; this.valuePromise = undefined; } public async getValue(): Promise<T> { if (this.isValueCreated) { return this.val as T; } const meStartedFactory = this.valuePromise === undefined; if (meStartedFactory) { this.valuePromise = this.valueFactory(); } // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const result = await this.valuePromise!; if (meStartedFactory) { this.val = result; this.valuePromise = undefined; this.isValueCreated = true; if (this.valueLifetime) { const timer = setTimeout(() => { this.isValueCreated = false; this.val = undefined; }, this.valueLifetime); // Do not hold the process waiting for the lifetime of the value to expire. timer.unref(); } } return result; } }