I have a method decorator that accepts a string key as an argument. It is being applied to a method, and I would like to access the method's parameters inside of the decorator declaration in order to use the method parameter(s) as the key. Is it possible to do something like this?
Note: I am using RxJS in this example to be able to cache the result after the network call
function CacheData(mapKey: string) {
return function(target: any, propertyKey: string, descriptor: PropertyDescription) {
descriptor.value = function(...args: any[]) {
if (sessionStorage.getItem(mapKey)) {
// return cached result
return of(sessionStorage.getItem(mapKey));
} else {
// return original network request call and cache result
return descriptor.value.apply(this, args).pipe(
tap(result => sessionStorage.setItem(mapKey, result));
);
}
}
return descriptor;
}
}
@CacheData(`key-${param1}`)
function getDetails(param1: string, param2: any): GetDetailsResponse {
return http.get(`https://swapi.dev/api/people/${param1}`).subscribe();
}
descriptor.value
This gives you control over its arguments. E.g.:
function CacheData(keyFn: (...keyArgs: any[]) => string) {
return function (
target: any,
propertyKey: string,
descriptor: PropertyDescriptor
) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) { // these are your args!
const key = keyFn(...args);
if (cache.hasOwnProperty(key)) {
return cache[key]; // return cached result
}
const result = originalMethod.apply(this, args);
cache[key] = result;
return result;
};
return descriptor;
};
}
You can apply the function like this:
@CacheData((param1: string, param2: number) => `key-${param1}-${param2}`)
function getDetails(param1: string, param2: any): GetDetailsResponse {
// implementation
}
in this case passing
(param1: string, param2: number) => `key-${param1}-${param2}`
as keyFn
.