Last active
October 11, 2019 22:55
-
-
Save cbejensen/735a408597a5d6d46474a80ce4bf8cc1 to your computer and use it in GitHub Desktop.
Memoization for asynchronous operations
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { ObservableInput, of, from } from 'rxjs'; | |
import { tap } from 'rxjs/operators'; | |
import { MemoizedFunction, MapCacheConstructor } from 'lodash'; | |
/** | |
* A copy of _.memoize, modified for async | |
* | |
* @see _.memoize | |
* | |
* @param func The function to have its output memoized. | |
* @param resolver The function to resolve the cache key. | |
* @return Returns a new memoizing function, which returns an Observable. | |
*/ | |
type ReturnObservableInput = (...args: any[]) => ObservableInput<any>; | |
export const memoAsync: { | |
<T extends ReturnObservableInput>(func: T, resolver?: (...args: any[]) => any): T & MemoizedFunction; | |
Cache: MapCacheConstructor; | |
} = (func: ReturnObservableInput, resolver?: (...args: any[]) => any): any => { | |
const memoized = function(...args) { | |
const key = resolver ? resolver.apply(this, args) : args[0]; | |
const cache = memoized.cache; | |
if (cache.has(key)) { | |
return of(cache.get(key)); | |
} | |
const observableInput: ObservableInput<any> = func.apply(this, args); | |
return from(observableInput).pipe(tap(res => memoized.cache.set(key, res))); | |
}; | |
memoized.cache = new (memoAsync.Cache || Map)(); | |
return memoized; | |
}; | |
memoAsync.Cache = Map; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Basically took Lodash's
memoize
function and adapted it to deal with async functions, so long as the async function returns an Observable, Promise, or other observable input.