【问题标题】:Using imported interceptor on controller not working in nestjs在控制器上使用导入的拦截器在nestjs中不起作用
【发布时间】:2020-02-18 06:57:38
【问题描述】:

我喜欢按照功能线组织我的项目,使用不同的模块来解决横切关注点,例如:配置、身份验证等。但是,当将 Interceptor 导入功能模块以与 Controller 一起使用时,Nest 似乎没有重用现有实例。

controllers.module.ts

@Module({
  imports: [
    // ConfigService is exported from this module.
    ConfigModule
  ],
  providers: [
    // For debugging purposes I used a factory so I could place a breakpoint and see
    // when the Interceptor is being created.
    {
      provide: MyInterceptor,
      useFactory: (config: ConfigService) => new MyInterceptor(config),
      inject: [
        ConfigService
      ]
    }
  ],
  exports: [
    MyInterceptor
  ]
})
export class ControllersModule {

}

customer.module.ts

@Module({
  imports: [
    ControllersModule
  ],
  controllers: [
    CustomerController
  ],
  providers: [
    CustomerService
  ]
})
export class CustomerModule {

}

customer.controller.ts

@Controller("/customers")
@UseInterceptors(MyInterceptor)
export class CustomerController {
  constructor(private readonly customerService: CustomerService) {

  }

  @Get()
  customers() {
    return this.customerService.findAll();
  }
}

当应用程序启动时,我可以看到MyInterceptor 提供程序工厂被调用,其中有一个ConfigService 的实例。但是然后我在控制台上看到以下错误

error: [ExceptionHandler] Nest can't resolve dependencies of the MyInterceptor (?). Please make sure that the argument ConfigService at index [0] is available in the CustomerModule context.

Potential solutions:
- If ConfigService is a provider, is it part of the current CustomerModule?
- If ConfigService is exported from a separate @Module, is that module imported within CustomerModule?
  @Module({
    imports: [ /* the Module containing ConfigService */ ]
  })

现在也许有一些关于 Nest 如何实例化/使用拦截器的事情我不理解,但我认为鉴于 MyInteceptor 已创建,并且 CustomerModule 导入的 ControllersModule bean 将可用并申请到CustomerController

这里有什么我遗漏的吗?

【问题讨论】:

    标签: nestjs


    【解决方案1】:

    拦截器(以及其他请求生命周期类)有点像pseudoproviders,因为它们是@Injectable(),但它们没有添加到providers 数组中进行绑定。你可以bind then via the providers array, (APP_INTERCEPTOR) 但这会导致它被全局绑定。

    由于无法按照您尝试的方式将拦截器添加到 providers 数组,因此您需要将 ConfigModule 添加到使用拦截器的任何模块中。

    【讨论】:

    【解决方案2】:

    作为旁注,您不应该在 Nestjs 中将 @Res 与拦截器一起使用

    为什么

    看,当你使用拦截器时,你正在处理(使用.handle())响应流(observable)而不是它的整个包,但是使用 express @987654325 @ 实际上以某种方式绕过了响应流的整个流程。

    nestjs official documents 中也明确提到了这一点:

    我们已经知道 handle() 返回一个 Observable。溪流 包含从路由处理程序返回的值,因此我们可以 使用 RxJS 的 map() 运算符轻松地对其进行变异。

    警告

    响应映射功能不适用于 特定于库的响应策略(直接使用 @Res() 对象 被禁止)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-12-16
      • 2021-02-11
      • 2021-09-04
      • 1970-01-01
      • 1970-01-01
      • 2020-04-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多