xref: /expo/packages/@expo/cli/src/utils/fn.ts (revision d187cc4c)
18d307f52SEvan Bacon/** `lodash.memoize` */
28d307f52SEvan Baconexport function memoize<T extends (...args: any[]) => any>(fn: T): T {
38d307f52SEvan Bacon  const cache: { [key: string]: any } = {};
48d307f52SEvan Bacon  return ((...args: any[]) => {
58d307f52SEvan Bacon    const key = JSON.stringify(args);
68d307f52SEvan Bacon    if (cache[key]) {
78d307f52SEvan Bacon      return cache[key];
88d307f52SEvan Bacon    }
98d307f52SEvan Bacon    const result = fn(...args);
108d307f52SEvan Bacon    cache[key] = result;
118d307f52SEvan Bacon    return result;
128d307f52SEvan Bacon  }) as any;
138d307f52SEvan Bacon}
14*d187cc4cSEvan Bacon
15*d187cc4cSEvan Bacon/** memoizes an async function to prevent subsequent calls that might be invoked before the function has finished resolving. */
16*d187cc4cSEvan Baconexport function guardAsync<V, T extends (...args: any[]) => Promise<V>>(fn: T): T {
17*d187cc4cSEvan Bacon  let invoked = false;
18*d187cc4cSEvan Bacon  let returnValue: V;
19*d187cc4cSEvan Bacon
20*d187cc4cSEvan Bacon  const guard: any = async (...args: any[]): Promise<V> => {
21*d187cc4cSEvan Bacon    if (!invoked) {
22*d187cc4cSEvan Bacon      invoked = true;
23*d187cc4cSEvan Bacon      returnValue = await fn(...args);
24*d187cc4cSEvan Bacon    }
25*d187cc4cSEvan Bacon
26*d187cc4cSEvan Bacon    return returnValue;
27*d187cc4cSEvan Bacon  };
28*d187cc4cSEvan Bacon
29*d187cc4cSEvan Bacon  return guard;
30*d187cc4cSEvan Bacon}
31