diff --git a/frontend/src/ts/utils/json-data.ts b/frontend/src/ts/utils/json-data.ts index e8e5ab2b207b..da84b000122d 100644 --- a/frontend/src/ts/utils/json-data.ts +++ b/frontend/src/ts/utils/json-data.ts @@ -35,34 +35,31 @@ async function fetchJson(url: string): Promise { /** * Memoizes an asynchronous function. - * @template P The type of the function's parameters. - * @template T The type of the function. - * @param {T} fn The asynchronous function to memoize. - * @param {(...args: Parameters) => P} [getKey] Optional function to generate cache keys based on function arguments. - * @returns {T} The memoized function. + * @template P Cache key type + * @template Args Function argument tuple + * @template R Resolved value of the Promise + * @param fn The async function to memoize. + * @param getKey Optional function to compute a cache key from the function arguments. If omitted, the first argument is used as the key. + * @returns A memoized version of the async function with the same signature. */ -export function memoizeAsync(...args: P[]) => Promise>( - fn: T, - getKey?: (...args: Parameters) => P, -): T { - const cache = new Map>>(); - - return (async (...args: Parameters): Promise> => { - const key = getKey ? getKey.apply(args) : (args[0] as P); - - if (cache.has(key)) { - const ret = await cache.get(key); - if (ret !== undefined) { - return ret as ReturnType; - } +export function memoizeAsync( + fn: (...args: Args) => Promise, + getKey?: (...args: Args) => P, +): (...args: Args) => Promise { + const cache = new Map>(); + + return async (...args: Args): Promise => { + const key = getKey ? getKey(...args) : (args[0] as P); + + const cached = cache.get(key); + if (cached) { + return cached; } - // oxlint-disable-next-line prefer-spread - const result = fn.apply(null, args) as Promise>; + const result = fn(...args); cache.set(key, result); - return result; - }) as T; + }; } /** @@ -70,9 +67,7 @@ export function memoizeAsync(...args: P[]) => Promise>( * @param url - The URL used to fetch JSON data. * @returns A promise that resolves to the cached JSON data. */ -export const cachedFetchJson = memoizeAsync( - fetchJson, -); +export const cachedFetchJson = memoizeAsync(fetchJson); /** * Fetches a layout by name from the server. @@ -92,17 +87,9 @@ export type LanguageProperties = Pick< let currentLanguage: LanguageObject; -/** - * Fetches the language object for a given language from the server. - * @param lang The language code. - * @returns A promise that resolves to the language object. - */ -export async function getLanguage(lang: Language): Promise { - // try { - if (currentLanguage === undefined || currentLanguage.name !== lang) { - const loaded = await cachedFetchJson( - `/languages/${lang}.json`, - ); +const cachedFetchLanguage = memoizeAsync( + async (lang: Language): Promise => { + const loaded = await fetchJson(`/languages/${lang}.json`); if (!isDevEnvironment()) { //check the content to make it less easy to manipulate @@ -116,6 +103,19 @@ export async function getLanguage(lang: Language): Promise { ); } } + return loaded; + }, +); +/** + * Fetches the language object for a given language from the server. + * @param lang The language code. + * @returns A promise that resolves to the language object. + */ +export async function getLanguage(lang: Language): Promise { + // try { + if (currentLanguage === undefined || currentLanguage.name !== lang) { + const loaded = await cachedFetchLanguage(lang); + currentLanguage = loaded; } return currentLanguage;