UNPKG

@naturalcycles/js-lib

Version:

Standard library for universal (browser + Node.js) javascript

56 lines (54 loc) 2.29 kB
// Based on: // https://github.com/mgechev/memo-decorator/blob/master/index.ts // http://decodize.com/blog/2012/08/27/javascript-memoization-caching-results-for-better-performance/ // http://inlehmansterms.net/2015/03/01/javascript-memoization/ // https://community.risingstack.com/the-worlds-fastest-javascript-memoization-library/ import { _getTargetMethodSignature } from './decorator.util.js'; import { jsonMemoSerializer, MapMemoCache } from './memo.util.js'; // memoSimple decorator is NOT exported. Only used in benchmarks currently /** * Memoizes the method of the class, so it caches the output and returns the cached version if the "key" * of the cache is the same. Key, by defaul, is calculated as `JSON.stringify(...args)`. * Cache is stored indefinitely in internal Map. * There is more advanced version of memo decorator called `memoCache`. * * Supports dropping it's cache by calling .dropCache() method of decorated function (useful in unit testing). */ export const memoSimple = (opt = {}) => (target, key, descriptor) => { if (typeof descriptor.value !== 'function') { throw new TypeError('Memoization can be applied only to methods'); } const originalFn = descriptor.value; // console.log(`${key} len: ${originalFn.length}`) // todo: optimization disabled until "default arg value" use case is solved (see memo.decorator.test.ts) /* let cache: MemoCache // Function with 0 arguments if (!originalFn.length) { cache = new SingleValueMemoCache() } else { // Function with > 0 arguments cache = new MapMemoCache() // cache = new ObjectMemoCache() } */ const cache = new MapMemoCache(); const { logger = console } = opt; const keyStr = String(key); const methodSignature = _getTargetMethodSignature(target, keyStr); descriptor.value = function (...args) { const ctx = this; const cacheKey = jsonMemoSerializer(args); if (cache.has(cacheKey)) { return cache.get(cacheKey); } const res = originalFn.apply(ctx, args); cache.set(cacheKey, res); return res; }; descriptor.value.dropCache = () => { logger.log(`${methodSignature} @memo.dropCache()`); cache.clear(); }; return descriptor; };