NodeJS NestJS:如何使用定制的装饰器访问控制器函数响应?

3okqufwl  于 2022-12-18  发布在  Node.js
关注(0)|答案(1)|浏览(123)

这是我的室内设计师

import { createParamDecorator, ExecutionContext } from "@nestjs/common";

export const CacheData = createParamDecorator(
    (data: any, ctx: ExecutionContext) => {
        const request = ctx.switchToHttp().getRequest();
        console.log(request.url, request.method, 'request');
        const response = ctx.switchToHttp().getResponse();
        const reqBody = request.body;
        console.log(reqBody, 'reqBody');
        console.log(response.raw.req.data, 'response');
        console.log(response.raw.req.body, 'response');
        console.log(response.raw.data, 'response');
        console.log(response.cacheData, 'response');
    }
);

在我的控制器函数中,我使用的装饰器如下所示:

getStringsArr(
    @Headers('Authorization') auth: string,
    @Headers('Country') country = 'DK',
    @CacheData() cacheData,
  ): Array<string> {
return ['Hello', 'World', '!'];
}

那么如何在CacheData装饰器中访问响应数据呢?

bq3bfh9z

bq3bfh9z1#

你的CacheData装饰器是一个param装饰器,这意味着,据我所知,它只会在方法处理程序被调用时执行。你有几个选择。这里有两个。

选项A -方法装饰器

方法装饰器可以给予你访问函数返回的数据,但也有缺点:你不能访问执行上下文,这与paramdecorator不同,而且注入客户服务也不那么优雅。我喜欢这个选项,因为它很容易为decorator提供参数。
由于您的示例是关于缓存的,我猜想您可能希望在那里注入服务,因此选项B可能更适合您的需求,但这里有一个带有方法装饰器的实现:

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', '!'];
}

选项B -路由拦截器

拦截器使依赖注入变得容易,因为它就像任何其他NestJS服务一样。如果你选择这个选项,我建议你阅读并理解request lifecycle
与装饰器相比,一个缺点是提供参数不太优雅,但是使用反射和方法装饰器是可行的:

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', '!'];
}

相关问题