如何编写需要角度为2的参数的服务构造函数?

时间:2017-02-22 16:16:39

标签: http angular service constructor components

我有一个声明MetricsService服务的组件。此服务需要http模块和两个定义主机和使用的auth密钥的字符串。

指标服务如下:

@Injectable()
export class MetricsService {
    constructor(
        private http: Http,
        public wsAuthKey: string,
        public wsHost: string
        ) {
        this.wsAuthKey  = wsAuthKey || "blahblahblahblahblahblahblahblah=";
        this.wsHost     = wsHost    || "https://preprod-admin.myservice.ws";
    }

使用它的组件编写如下:

export class DatavizComponent implements OnInit, OnChanges {
    constructor(
        private zms: MetricsService,
    ) { 
    }

我的问题是我应该如何编写组件构造函数以便整个工作正常,包括传递主机和密钥(但不传递http)?

注意:当前编写的代码无法编译。

更确切地说,我希望该组件提供类似于应用程序的数据:

 export class DatavizComponent implements OnInit, OnChanges {
        constructor(
            private zms = MetricsService("http://myhost.com", "mykey"),
        ) { 
        }

但如果这样可行,如何传递http?

建议解决方案后更新:

export class MetricsService {

    constructor(
        private http: Http,
        @Inject('wsAuthKey') @Optional() public wsAuthKey?: string,
        @Inject('wsHost') @Optional() public wsHost?: string
        ) {
        this.wsAuthKey  = wsAuthKey || "blahblah=";
        this.wsHost     = wsHost    || "https://preprod-admin.host.ws";


        console.log("MetricsService constructor="
            + " wsAuthKey="+this.wsAuthKey
            + ", wsHost="+this.wsHost
        );

    }

在组件中:

@Component({
    selector:    'dataviz-offers-volumes',
    templateUrl: 'app/dataviz.component.html',
    styleUrls:  ['app/dataviz.component.css'],
    encapsulation: ViewEncapsulation.None,
    providers: [
        {provide: 'wsAuthKey',  useValue: 'abc'}, 
        {provide: 'wsHost',     useValue: 'efg'}, 
    ],
})
export class DatavizComponent implements OnInit, OnChanges {

    @ViewChild('chart') private chartContainer: ElementRef;
    @Input() private graphId:string;
    @Input() private wsAuthKey:string;
    @Input() private wsHost:string;
    @Input() private maxSamples=12;

    constructor(
        private zms: MetricsService
    ) { 
    }

在构造函数中,日志如下(值不传递):

MetricsService constructor= wsAuthKey=blahblah=, wsHost=https://preprod-admin.host.ws

它应该显示' abc'和' efg'。

但是我想知道使用dataviz componentsnet的组件是否存在问题。 在此组件中,已传递以下信息:

@Input() private wsAuthKey:string;
@Input() private wsHost:string;

我希望标签可选择预设主机和密钥:

                <h1>dataviz volume</h1>
                <div class="chartContainer left" title="Simultaneous offers via dataviz directive">
                    <dataviz-offers-volumes 
                        id="dataviz-volumes1"
                        [graphId]="graphId"
                        [wsAuthKey]="'myauthkey'"
                        [wsHost]="'http://myhost.com'"
                        [maxSamples]="123"
                    >
                    </dataviz-offers-volumes>
                </div>

3 个答案:

答案 0 :(得分:27)

您可以通过添加@Optional()(DI)和?(TypeScript)以及@Inject(somekey)为不支持作为提供者密钥的原始值使参数成为可选参数

@Injectable()
export class MetricsService {
    constructor(
        private http: Http,
        @Inject('wsAuthKey') @Optional() public wsAuthKey?: string,
        @Inject('wsHost') @Optional() public wsHost?: string
        ) {
        this.wsAuthKey  = wsAuthKey || "blahblahblahblahblahblahblahblah=";
        this.wsHost     = wsHost    || "https://preprod-admin.myservice.ws";
    }
providers: [
  {provide: 'wsAuthKey', useValue: 'abc'}, 
  {provide: 'wsHost', useValue: 'efg'}, 
]

如果提供了它们,它们会被传递,否则它们会被忽略,但是DI仍然可以注入MetricsService

答案 1 :(得分:11)

这是this question中特别描述的常见配方。它应该是一个包含配置的服务:

@Injectable()
export class MetricsConfig {
  wsAuthKey = "blahblahblahblahblahblahblahblah=";
  wsHost = "https://preprod-admin.myservice.ws";
}

@Injectable()
export class MetricsService {
    constructor(
        private http: Http,
        metricsConfig: MetricsConfig
    ) {
        this.wsAuthKey  = metricsConfig.wsAuthKey;
        this.wsHost     = metricsConfig.wsHost;
    }
}

在需要更改的情况下,可以为整个模块或特定组件覆盖或扩展它:

@Component(
  ...
  { provide: MetricsConfig, useClass: class ExtendedMetricsConfig { ... } }
)
export class DatavizComponent ...

在这种情况下,没有必要让MetricsConfig成为一个班级。它也可以是OpaqueToken值提供者。但是一个类可以方便地扩展,它更容易注入,并且已经提供了一个打字界面。

答案 2 :(得分:0)

来自官方文档:https://angular.io/guide/dependency-injection-in-action#injectiontoken

在构造函数中使用@Optional装饰器:

export class MyService {
  constructor( @Optional() public var: type = value ) { }
}