Skip to content

Instantly share code, notes, and snippets.

@davidecavaliere
Created January 15, 2020 17:06
Show Gist options
  • Save davidecavaliere/70f9f77dcef70336317cd91583bff3ad to your computer and use it in GitHub Desktop.
Save davidecavaliere/70f9f77dcef70336317cd91583bff3ad to your computer and use it in GitHub Desktop.
export function Cache(options: CacheOptions) {
let lastCallArguments: any[] = [];
return (target, propertyKey: string, descriptor) => {
Reflect.metadata(CacheMetadata, options)(target);
const originalFunction = descriptor.value;
target[`${propertyKey}_cached`] = new ReplaySubject(1, options.ttl);
descriptor.value = function(...args) {
// i'm not able to capture a defaulting that happens at function level
/*
ie:
```
@Cache(...)
public findAll(id: number = 1) { ... }
```
if the function is called like`service.findAll();` then args would be [] but `originalFunction` will actually call the service with [1]
Is there a way to capture the defaulting mechanism?
*/
// args changed?
let argsNotChanged = true;
for (let i = 0; i < lastCallArguments.length; i++) {
argsNotChanged = argsNotChanged && lastCallArguments[i] == args[i];
}
if (!argsNotChanged) { // args change
this[`${propertyKey}_cached`] = new ReplaySubject(1, options.ttl);
}
lastCallArguments = args;
const req: Observable<any> = originalFunction.apply(this, args).pipe(
tap((response) => {
this[`${propertyKey}_cached`].next(response);
})
);
// despite what the documentation says i can't find that the complete is ever called
return race(this[`${propertyKey}_cached`], req);
};
return descriptor;
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment