【问题标题】:typedi constructor injection return undefinedtypedi 构造函数注入返回未定义
【发布时间】:2021-12-31 02:30:47
【问题描述】:

我在 Node (express) 项目中使用 typedi。 我不明白为什么在我的服务类中,注入可以作为属性注入但不能作为构造函数注入。

这行得通:

@Service()
export default class AuthService {
  @Inject("logger") private logger
  @Inject("eventEmitter")
  private eventEmitter!: EventEmitter;
   
  constructor(

  ) {}
}

虽然这不起作用:

@Service()
export default class AuthService {
  @Inject("logger") private logger
  @Inject("eventEmitter")
  private eventEmitter!: EventEmitter;
   
  constructor(
      @Inject("logger") private logger,
      @Inject("eventEmitter") private eventEmitter: EventEmitter
  ) {}
}

作为一个例子,我使用记录器和发射器如下:

  public async SignUp(
    userInputDTO: IUserInputDTO
  ): Promise<{ user: IUser; token: string }> {
    try {
      //some code
      this.logger.silly("Hashing password");
      const hashedPassword = await argon2.hash(userInputDTO.password, { salt });
      this.logger.silly("Creating user db record");
      this.eventEmitter.emit(userEvent.signUp);
      //some code

      return {
        user: { },
        token: "myToken",
      };
    } catch (e) {
      this.logger.error(e);
      throw e;
    }
  }

在第一种情况下,它按预期工作,但在第二种情况下,this.eventEmitter 和 this.logger 未定义。

附注:

  • 不存在循环依赖
  • 我导入了“reflect-metadata”,实际上,如果将装饰器放在属性上而不是在构造函数的参数中,则装饰器可以正常工作
  • typedi,除非这个问题可以正常工作。我可以毫无问题地使用 Container#get 、 Container#set

【问题讨论】:

    标签: javascript node.js typescript express dependency-injection


    【解决方案1】:

    在第二个代码 sn-p 中,您已经用 @Service() 装饰了 AuthService,这应该足够了。

    所以改成这个试试看:

    @Service()
    export default class AuthService {
    
      constructor(
          private logger: YOU_NEED_A_TYPE_HERE,
          private eventEmitter: EventEmitter
      ) {}
    }
    

    只需确保将YOU_NEED_A_TYPE_HERE 更改为记录器的实际类型,否则将无法正常工作。

    然后你应该有你的 loggereventEmitter 参考可用:

    public async SignUp(
        userInputDTO: IUserInputDTO
      ): Promise<{ user: IUser; token: string }> {
        try {
        
        // logger and eventEmitter should have the right values
    
    

    【讨论】:

    • 感谢您的回复。我添加了类型,因为我认为最好让它明确。无论如何,即使没有显式类型,它也开始工作。如果有兴趣,请查看我的答案
    • 是的。根据 typedi 文档,您需要在 tsconfig.json 内将两个标志都设置为 true(即“emitDecoratorMetadata”:true、“experimentalDecorators”:true)。
    【解决方案2】:

    它开始工作,但我不确定是什么原因造成的。

    • 我在另一台具有较新节点版本的机器上工作(这个问题中的示例在 node12 上运行,而它开始使用 node16)。

    • 我在tsconfig.json 中添加了一条缺失的行。

      “emitDecoratorMetadata”:真,

    "experimentalDecorators": true 已经在那里了。

    也许是时候设置一个小容器在不同的节点版本中测试它了。

    作为旁注,似乎并不严格要求向构造函数参数添加显式类型以进行注入(但无论如何建议)。此外,只要类已经用 @Service 装饰,@Inject 装饰器似乎也是不必要的

    【讨论】:

      猜你喜欢
      • 2021-03-17
      • 2021-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-15
      • 2018-10-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多