【问题标题】:Access Nest "injector" in a custom interceptor在自定义拦截器中访问 Nest“注入器”
【发布时间】:2019-01-14 23:21:08
【问题描述】:

我需要在intercept 函数内访问一个服务(由Nest TypeOrmModule 提供)(重要提示:不是constructor 参数!!!)因为这取决于传递的选项(在这种情况下为entity)。

服务注入令牌由getRepositoryToken 函数提供。

export class PaginationInterceptor {
  constructor(private readonly entity: Function) {}

  intercept(context: ExecutionContext, call$: Observable<any>): Observable<any> {
    // Here I want to inject the TypeORM repository.
    // I know how to get the injection token, but not HOW to
    // get the "injector" itself.
    const repository = getRepositoryToken(this.entity);

    // stuff...

    return call$;
  }
}

Nest 中有“服务容器”的概念吗?这个github issue 对我没有帮助。

示例用法(控制器操作):

  @Get()
  @UseInterceptors(new PaginationInterceptor(Customer))
  async getAll() {
    // stuff...
  }

【问题讨论】:

    标签: node.js typescript nestjs typeorm


    【解决方案1】:

    您可以使用NestFactory 创建NestApplication 实例来注入任何提供程序或控制器。

    示例

    假设您的AppModule 中有以下提供程序:

    providers: [{provide: 'MyToken', useValue: 'my-value'}]
    

    然后你可以在任何地方注入这个提供者:

    // Creates an instance of the NestApplication
    const application = await NestFactory.create(AppModule);
    
    // Retrieves an instance of either injectable or controller available anywhere, otherwise, throws exception.
    const myValue = application.get('MyToken');
    
    console.log(myValue); // -> my-value
    

    【讨论】:

    • 不是我问的,但是谢谢。我需要从拦截器本身内部使用 app.get('MyToken')。
    【解决方案2】:

    关于依赖注入(如果你真的想要/需要它),我想使用mixin 类可以解决问题。请参阅v4 documentation(高级 > Mixin 类)。

    import { NestInterceptor, ExecutionContext, mixin, Inject } from '@nestjs/common';
    import { getRepositoryToken } from '@nestjs/typeorm';
    import { Observable } from 'rxjs';
    import { Repository } from 'typeorm';
    
    export function mixinPaginationInterceptor<T extends new (...args: any[]) => any>(entityClass: T) {
      // declare the class here as we can't give it "as-is" to `mixin` because of the decorator in its constructor
      class PaginationInterceptor implements NestInterceptor {
        constructor(@Inject(getRepositoryToken(entityClass)) private readonly repository: Repository<T>) {}
    
        intercept(context: ExecutionContext, $call: Observable<any>) {
          // do your things with `this.repository`
          return $call;
        }
      }
    
      return mixin(PaginationInterceptor);
    }
    

    免责声明:这是有效的 TypeScript 代码,但我没有机会在实际项目中对其进行测试,因此可能需要进行一些返工。我们的想法是像这样使用它:

    @UseInterceptors(mixinPaginationInterceptor(YourEntityClass))
    

    如果您对代码有任何疑问,请告诉我。但是我觉得mixin 的文档还不错!


    OR 你也可以使用getRepository from typeorm(传递实体类)。 这不是 DI,因此,您必须使用 spyOngetRepository 函数才能进行正确的测试。


    关于容器,我几乎可以肯定访问它的唯一方法是使用 Execution Context,正如 Kim 所指出的那样。

    【讨论】:

    • 非常感谢!这就是我的意思。有效,但稍作修改。我无法理解这里的类型提示,它们也不正确(实体类不能分配给T,缺少原型)......为什么&lt;T extends new (...args: any[]) =&gt; any&gt;(entityClass: T)?为什么要使用 mixin 而不是使用原生打字稿 return class
    • 嘿! ➵ new (...args: any[]) =&gt; any 在某种程度上是定义“类类型”的一种方式。顺便说一句,您可以在 TypeORM 导出中看到 ClassType 定义。这几乎不一样,但它不能很好地与getRepositoryToken 所期望的Function 类型配合使用。 ➵ mixin 自动将给定的 mixinClass 声明为 Injectable(请参阅它的代码源代码在 Nest repo,component.decorator.ts
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-25
    • 2016-04-25
    • 1970-01-01
    • 2012-02-01
    • 2020-05-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多