为啥在这个 angular2 示例中我仍然需要 @inject?

Posted

技术标签:

【中文标题】为啥在这个 angular2 示例中我仍然需要 @inject?【英文标题】:Why do I still need @inject in this angular2 example?为什么在这个 angular2 示例中我仍然需要 @inject? 【发布时间】:2016-11-02 15:28:36 【问题描述】:

这可能是一种特殊情况(注入浏览器本机窗口对象),但是我有点困惑,为什么当我的类已经有一个 @Injectable() 装饰器时我仍然需要 @Inject() 参数装饰器.

以这个简化的例子为例:

import  provide, bootstrap, Injectable, Inject  from '@angular/core';


@Injectable()
export class Token 
  private token: string;

  public constructor(token: string, window: Window) 
    this.token = window.atob(token);
  ;

  public getToken(): string 
    return this.token;
  



@Injectable()
export class TokenFactory 
  private window: Window;

  public constructor(window: Window) 
    this.window = window;
  

  public createToken(token: string): Token 
    return new Token(token, this.window);
  



@Component(
  template:   `
    <p *ngFor="let token of tokens">
      Encoded: token.getToken()
    </p>
  `,
  providers:  [ TokenFactory ]
)
class MainComponent 
  public tokens: Token[];

  public constructor(factory: TokenFactory) 
    this.tokens = [
      factory.create('token-1'),
      factory.create('token-2')
    ];
  ;



bootstrap(
  MainComponent, [
    provide(Window,  useValue: window )
]);

概述:我们有一个令牌类,它表示一个对象,该对象可以在组件或另一个服务中多次存在(因此没有单例)。令牌类取决于全局窗口对象(例如,对于 base64 编码)。 为了使其可测试,我们在引导期间为全局 window object 定义了一个应用范围的提供程序,而不是直接在令牌服务中使用它。

主要组件需要动态创建令牌,所以我们创建并注入一个简单的工厂服务TokenFactory,它也需要窗口提供者(在构建过程中将令牌类传递给它)。

问题:在出现错误的浏览器中执行时失败

Can't resolve all parameters for TokenFactory: (?).

但可以通过在工厂构造函数 window 参数中添加 @Inject(Window) 装饰器来修复。

现在,我有点困惑,因为大多数指南/教程都解释说,在使用 Injectable 装饰器装饰类时,打字稿中不需要注入装饰器,那么为什么不使用 @Inject( ) 装饰器?

配置: emitDecoratorMetadataexperimentalDecorators 设置已启用,我正在使用 tsc 1.8.10 和 angular2 rc.3.


PS: 我也愿意接受一般的设计改进。

(例如,在生产场景中,我可能只会导出 Token 接口而不是整个类)

【问题讨论】:

您能否详细介绍一下 Window 类的定义位置以及如何导入它?谢谢! 它的浏览器全局 window object 暴露为 window (情人案例)。它在引导期间被注入底部。嗯...,在这种情况下,provider-name 是否必须是字符串或更好的是 OpaqueToken,因为 typescript/angular 可能会混淆 Window name 属性? 我忘了说,这是一个运行时(浏览器)错误而不是编译时(tsc)... 【参考方案1】:

我不清楚这个问题实际上是关于什么的,但是

如果没有@Inject(...),为可注入的构造函数参数键入string 没有任何意义

@Injectable()
export class Token 
  private token: string;

  public constructor(token: string, window: Window)  // <<== invalid
    this.token = window.atob(token);
  ;

  public getToken(): string 
    return this.token;
  

但是因为你使用它喜欢

new Token(token, this.window);

似乎应该从这个类中删除@Injectable()


关于错误消息:看起来Window 没有正确导入或者不是类型而是OpaqueTokenstring

如果依赖注入应该使用与参数类型不同的键,则需要@Inject()。在您的情况下,它看起来像 Window 不是类型(类),因此在这样使用时不起作用。

【讨论】:

很好,你说得对,我应该删除 Token 类的可注入对象,因为 token 参数不是要注入的,实际上更多的是输入参数。您对窗口的评论敲响了警钟,因为窗口 object 来自浏览器,它可能没有被装饰(没有元数据),因此角度需要工厂窗口参数上的 Inject docorator;听起来不错。

以上是关于为啥在这个 angular2 示例中我仍然需要 @inject?的主要内容,如果未能解决你的问题,请参考以下文章

如果wen可以定义公共属性,Angular2为啥要使用getter

为啥此代码示例中需要 @Output EventEmitter?

为啥在 iOS 7 中我的本地通知没有显示横幅

Angular 2 动态嵌套表单

为啥 C# 中的诚实函数示例仍然不诚实?

将 ES6 模块与 WebPack 一起使用,为啥仍然需要 require