Your CacheData
decorator is a param decorator, which means, as far as I know, that it will be executed only when the method handler is called. You have a few options. Here are two.
Option A - Method decorator
A method decorator would give you access to the returned data from your function but comes with drawbacks: you don't have access to the execution context, unlike the param decorator and injecting customer services is less elegant. I like this option because it is easy to supply parameters to the decorator.
Since your example is around caching, I suspect you'll want to inject your service there, so option B is probably more fitted to your requirements, but here's an implementation with a method decorator :
const MyMethodDecorator = (params) => {
return (
target: Record<string, unknown>,
_propertyKey: string,
descriptor: PropertyDescriptor,
) => {
const originalMethod = descriptor.value;
descriptor.value = async function (...args) {
const data = await originalMethod.apply(this, args);
// data = ['Hello', 'World', '!']
};
return descriptor;
};
};
@MyMethodDecorator({ ttl: 120, cacheKey: 'stringsArr' })
getStringsArr(
@Headers('Authorization') auth: string,
@Headers('Country') country = 'DK'
): Array<string> {
return ['Hello', 'World', '!'];
}
Option B - Route Interceptor
Interceptors make dependency injection easy since it's like any other NestJS service. I recommend reading and understanding the request lifecycle is you choose this option.
One drawback vs a decorator is that supplying parameters is less elegant but is doable using reflection and a method decorator:
import { applyDecorators, SetMetadata, UseInterceptors } from '@nestjs/common';
@Injectable()
export class MyInterceptor implements NestInterceptor {
constructor(private readonly reflector: Reflector) {}
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const params = this.reflector.get('MyInterceptorMetadataKey', context.getHandler());
// params = { ttl: 120, cacheKey: 'stringsArr' }
return next.handle().pipe(
tap((response) => {
// data = ['Hello', 'World', '!']
}),
);
}
}
const MyMethodDecorator = (params) =>
applyDecorators(SetMetadata('MyInterceptorMetadataKey', params));
@UseInterceptors(MyInterceptor)
@MyMethodDecorator({ ttl: 120, cacheKey: 'stringsArr' })
getStringsArr(
@Headers('Authorization') auth: string,
@Headers('Country') country = 'DK'
): Array<string> {
return ['Hello', 'World', '!'];
}