-
-
Save janpauldahlke/1e5fd067da790bd39724ea7f572a71a4 to your computer and use it in GitHub Desktop.
Using memoizee with observables
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 { decorate } from 'core-decorators'; | |
import * as memoize from 'memoizee'; | |
import { duration, unitOfTime } from 'moment'; | |
import { memoizeObservable } from './rxjs'; | |
type HumanDuration = [number, unitOfTime.DurationConstructor]; | |
export interface MemoizeOptions extends memoize.Options { | |
observable?: boolean; | |
ttl?: HumanDuration; | |
} | |
export function Memoize(options: MemoizeOptions) { | |
const wrapperFunction = options.observable ? | |
memoizeObservable : memoize; | |
if (options.ttl) { | |
options = { | |
...options, | |
maxAge: duration(...options.ttl).asMilliseconds(), | |
}; | |
} | |
return decorate.call(this, wrapperFunction, options); | |
} |
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 * as memoizee from 'memoizee'; | |
import { pipe, Subject } from 'rxjs'; | |
import { share, takeUntil } from 'rxjs/operators'; | |
type ObservableFunction = <T>(args: any[]) => Observable<T>; | |
export function memoizeObservable(toWrap: ObservableFunction, options: memoizee.Options) { | |
const disposeSymbol = Symbol('___dispose'); | |
const newOptions: memoizee.Options = Object.assign({ | |
normalizer: (args: any[]) => { | |
// not sure why this is needed? without it all arguments yield the same cached value | |
return Array.from(args); | |
}, | |
}, options, { | |
dispose(value: any) { | |
value[disposeSymbol](); | |
}, | |
}); | |
return memoizee(function() { | |
const result$ = toWrap.apply(this, arguments); | |
const expired$ = new Subject(); | |
const sharedResult$ = result$.pipe(takeUntil(expired$), shareReplay(1)); | |
(sharedResult$ as any)[disposeSymbol] = () => expired$.next(); | |
return sharedResult$; | |
}, newOptions); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment