Skip to content

Instantly share code, notes, and snippets.

@OysteinAmundsen
Last active April 7, 2022 09:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save OysteinAmundsen/b97a2359292463feb8c0e2270ed6695a to your computer and use it in GitHub Desktop.
Save OysteinAmundsen/b97a2359292463feb8c0e2270ed6695a to your computer and use it in GitHub Desktop.
Decorator for sharing the result given from function that returns an observable
import { finalize, Observable, share } from 'rxjs';
/**
* If you have more than one component calling a function which returns an observable,
* this will create the observable many times. For http requests, this will result in
* many requests being made and thus redundant http calls.
*
* The SharedObservable will make sure that all calls made simultaneously will only
* perform 1 http call and all subscribers share the same response.
* This will also take into account different input parameters and create a new
* request if the parameters are different.
*
* USAGE:
*
* @SharedObservable()
* myFunc(id: number): Observable<any> {
* return this.http.get<any>(`/api/someUrl/${id}`);
* }
*/
export function SharedObservable(): MethodDecorator {
const obs$ = new Map<string, Observable<any>>();
return (target: any, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
const key = JSON.stringify(args);
if (!obs$.has(key)) {
// We have no observable for this key yet, so we create one
const res = originalMethod.apply(this, args).pipe(
share(), // Make the observable hot
finalize(() => obs$.delete(key)) // Cleanup when observable is complete
);
obs$.set(key, res);
}
// Return the cached observable
return obs$.get(key);
};
return descriptor;
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment