packages/shared/util/Recoil_Memoize.js (63 lines of code) (raw):

/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @emails oncall+recoil * @flow strict-local * @format */ 'use strict'; /** * Caches a function's results based on the key returned by the passed * hashFunction. */ function memoizeWithArgsHash<TArgs: $ReadOnlyArray<mixed>, TReturn>( fn: (...TArgs) => TReturn, hashFunction: (...TArgs) => string, ): (...TArgs) => TReturn { let cache; const memoizedFn: (...TArgs) => TReturn = (...args: TArgs): TReturn => { if (!cache) { cache = ({}: {[string]: TReturn}); } const key = hashFunction(...args); if (!Object.hasOwnProperty.call(cache, key)) { cache[key] = fn(...args); } return cache[key]; }; return memoizedFn; } /** * Caches a function's results based on a comparison of the arguments. * Only caches the last return of the function. * Defaults to reference equality */ function memoizeOneWithArgsHash<TArgs: $ReadOnlyArray<mixed>, TReturn>( fn: (...TArgs) => TReturn, hashFunction: (...TArgs) => string, ): (...TArgs) => TReturn { let lastKey: ?string; let lastResult: TReturn; // breaking cache when arguments change const memoizedFn: (...TArgs) => TReturn = (...args: TArgs): TReturn => { const key = hashFunction(...args); if (lastKey === key) { return lastResult; } lastKey = key; lastResult = fn(...args); return lastResult; }; return memoizedFn; } /** * Caches a function's results based on a comparison of the arguments. * Only caches the last return of the function. * Defaults to reference equality */ function memoizeOneWithArgsHashAndInvalidation< TArgs: $ReadOnlyArray<mixed>, TReturn, >( fn: (...TArgs) => TReturn, hashFunction: (...TArgs) => string, ): [(...TArgs) => TReturn, () => void] { let lastKey: ?string; let lastResult: TReturn; // breaking cache when arguments change const memoizedFn: (...TArgs) => TReturn = (...args: TArgs): TReturn => { const key = hashFunction(...args); if (lastKey === key) { return lastResult; } lastKey = key; lastResult = fn(...args); return lastResult; }; const invalidate = () => { lastKey = null; }; return [memoizedFn, invalidate]; } module.exports = { memoizeWithArgsHash, memoizeOneWithArgsHash, memoizeOneWithArgsHashAndInvalidation, };