Skip to content

Instantly share code, notes, and snippets.

@cbejensen
Last active October 11, 2019 22:55
Show Gist options
  • Save cbejensen/735a408597a5d6d46474a80ce4bf8cc1 to your computer and use it in GitHub Desktop.
Save cbejensen/735a408597a5d6d46474a80ce4bf8cc1 to your computer and use it in GitHub Desktop.
Memoization for asynchronous operations
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;
@cbejensen
Copy link
Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment