89 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			89 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | 'use strict'; | ||
|  | const mimicFn = require('mimic-fn'); | ||
|  | const isPromise = require('p-is-promise'); | ||
|  | const mapAgeCleaner = require('map-age-cleaner'); | ||
|  | 
 | ||
|  | const cacheStore = new WeakMap(); | ||
|  | 
 | ||
|  | const defaultCacheKey = (...arguments_) => { | ||
|  | 	if (arguments_.length === 0) { | ||
|  | 		return '__defaultKey'; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	if (arguments_.length === 1) { | ||
|  | 		const [firstArgument] = arguments_; | ||
|  | 		if ( | ||
|  | 			firstArgument === null || | ||
|  | 			firstArgument === undefined || | ||
|  | 			(typeof firstArgument !== 'function' && typeof firstArgument !== 'object') | ||
|  | 		) { | ||
|  | 			return firstArgument; | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return JSON.stringify(arguments_); | ||
|  | }; | ||
|  | 
 | ||
|  | const mem = (fn, options) => { | ||
|  | 	options = Object.assign({ | ||
|  | 		cacheKey: defaultCacheKey, | ||
|  | 		cache: new Map(), | ||
|  | 		cachePromiseRejection: false | ||
|  | 	}, options); | ||
|  | 
 | ||
|  | 	if (typeof options.maxAge === 'number') { | ||
|  | 		mapAgeCleaner(options.cache); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	const {cache} = options; | ||
|  | 	options.maxAge = options.maxAge || 0; | ||
|  | 
 | ||
|  | 	const setData = (key, data) => { | ||
|  | 		cache.set(key, { | ||
|  | 			data, | ||
|  | 			maxAge: Date.now() + options.maxAge | ||
|  | 		}); | ||
|  | 	}; | ||
|  | 
 | ||
|  | 	const memoized = function (...arguments_) { | ||
|  | 		const key = options.cacheKey(...arguments_); | ||
|  | 
 | ||
|  | 		if (cache.has(key)) { | ||
|  | 			return cache.get(key).data; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		const cacheItem = fn.call(this, ...arguments_); | ||
|  | 
 | ||
|  | 		setData(key, cacheItem); | ||
|  | 
 | ||
|  | 		if (isPromise(cacheItem) && options.cachePromiseRejection === false) { | ||
|  | 			// Remove rejected promises from cache unless `cachePromiseRejection` is set to `true`
 | ||
|  | 			cacheItem.catch(() => cache.delete(key)); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		return cacheItem; | ||
|  | 	}; | ||
|  | 
 | ||
|  | 	try { | ||
|  | 		// The below call will throw in some host environments
 | ||
|  | 		// See https://github.com/sindresorhus/mimic-fn/issues/10
 | ||
|  | 		mimicFn(memoized, fn); | ||
|  | 	} catch (_) {} | ||
|  | 
 | ||
|  | 	cacheStore.set(memoized, options.cache); | ||
|  | 
 | ||
|  | 	return memoized; | ||
|  | }; | ||
|  | 
 | ||
|  | module.exports = mem; | ||
|  | // TODO: Remove this for the next major release
 | ||
|  | module.exports.default = mem; | ||
|  | 
 | ||
|  | module.exports.clear = fn => { | ||
|  | 	const cache = cacheStore.get(fn); | ||
|  | 
 | ||
|  | 	if (cache && typeof cache.clear === 'function') { | ||
|  | 		cache.clear(); | ||
|  | 	} | ||
|  | }; |