I am looking for the best way of implementing an optimization for very expensive method that takes multiple parameters and returns an Observable. Is there an elegant way of doing it?
What I am looking for is prettier version of this:
class Example {
constructor(
private databaseService: DatabaseService,
private someService: SomeService)
expensive(param1: string, param2: string) : Observable<string> {
if (isMemoraized(param1,param2) {
return Observable.create(observer=>
observer.next(memorizedValue(param1, param2));
observer.complete();
} else {
return Observable.create(observer=>{
Observable.forkJoin([
this.databaseService.getValue(param1, param2),
this.someService.fetchDataFromServer(param2)].subscribe(
results => {
let result = results[0] + ' ' + results[1];
memorizeValue([param1,param2], result);
observer.next(result);
observer.complete();
});
});
}
}
}
Any help appreciated!
You can create a decorator to memoize the results in run-time for every decorated function:
function Memoized() {
return function(
target: any,
propertyKey: string,
descriptor: PropertyDescriptor
) {
const method = descriptor.value; // references the method being decorated
let cacheMember = propertyKey + "CacheMember";
// the Observable function
if (!descriptor.value) {
throw new Error("use MemoizeDecorator only on services methods");
}
descriptor.value = function(...args) {
if (!target[cacheMember]) {
let returnedObservable = method.apply(this, args);
if (!(returnedObservable instanceof Observable)) {
throw new Error(
`method decorated with Memoized Decorator must return Observable`
);
}
target[cacheMember] = returnedObservable.pipe(
publishReplay(),
refCount()
);
}
return target[cacheMember];
};
};
}
Usage:
@Memoized()
expensive(param1: string, param2: string) : Observable<string> {
// ...the expensive task
}
Warning! Decorators are stage 2 proposal of js! Don't use decorators without transpiling your code (Typescript supports it completely)
There are a number of memoization packages available on NPM. For TypeScript, I'd recommend typescript-memoize, which will provide you with a decorator you can use to memoize your methods.
For example:
import {Memoize} from 'typescript-memoize';
class Example {
@Memoize((param1: string, param2: string) => {
return param1 + ';' + param2;
})
expensive(param1: string, param2: string) : Observable<string> {
// ...
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With