Angular2“服务"如何将一项服务注入另一项(单例)? [英] Angular2 "Services" how to @inject one service into another (singletons)?

查看:65
本文介绍了Angular2“服务"如何将一项服务注入另一项(单例)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何将一项服务注入另一项服务?例如,假设我有一个需要另一个收藏夹的收藏夹(TeamCollection => PlayerCollection).目前,我只是创建两个单独的集合,并使用类似以下内容的东西:

import {PlayerCollection} from "<<folder>>/player";

但这需要我在Typescript中为我想成为一个单例实例的每个服务编写自己的单例getInstance代码.

执行此操作的正确方法是什么?我希望在组件中同时拥有两个单例,并且能够使用构造函数语法将一个服务@Inject注入另一个服务,而无需创建新的单例实例.

class TeamCollection {    
    constructor(@Inject(PlayerCollection): PlayerCollection) {}
}

解决方案

因此,在重新阅读了Pascal Precht的精彩文章后: http://twofuckingdevelopers.com/2015/04/angular- 2单服务/

使用Angular 2的DI注入的所有东西都已经是Singleton.不需要这种服务"

我去测试了,现在发现的内容都回答了我的问题,并使我对angular2中的DI主题更加困惑.

请参见以下代码:

team.ts

import {BaseCollection, BaseModel} from "./base";
import {PlayerCollection} from './player';
import {Injectable, Inject} from "angular2/angular2";

@Injectable()
export class TeamCollection extends BaseCollection {
    playerCollection: PlayerCollection;
    constructor(@Inject(PlayerCollection) playerCollection: PlayerCollection) {
        super();
        this.playerCollection = playerCollection;
    }

    create(data: Object): TeamModel {
        return new TeamModel(data);
    }
}

player.ts

import {BaseCollection, BaseModel} from "./base";
import {Injectable} from "angular2/angular2";

@Injectable()
export class PlayerCollection extends BaseCollection {
    create(data: Object): PlayerModel {
        return new PlayerModel(data);
    }
}

team.spec.ts

/// <reference path="../../typings.d.ts" />

//VERY IMPORTANT TO ALWAYS LOAD THESE
import 'zone.js';
import 'reflect-metadata';
import 'es6-shim';

import {TeamModel, TeamCollection} from "../../app/model/team";
import {PlayerCollection} from "../../app/model/player";
import {Inject, Injector} from "angular2/angular2";

describe('TeamCollection', () => {
  var teamCollection: TeamCollection;
  var playerCollection: PlayerCollection; 
  beforeEach(() => {
      var injector = Injector.resolveAndCreate([
        TeamCollection,
        PlayerCollection
      ]);
      teamCollection = injector.get(TeamCollection);  

      var injectorT = Injector.resolveAndCreate([
        PlayerCollection
      ]);
      playerCollection = injector.get(PlayerCollection);
  });

  it('should have a singleton PlayerCollection shared between all classes within the application', () => {
    console.log(teamCollection.playerCollection.uuId);
    console.log(playerCollection.uuId);
  });  
});

只要是创建它们的相同注入器(var injector),它们就共享相同的uuID.虽然当我使用第二个注入器(var injectorT)时,UUID是不同的,这意味着将创建playerCollection的新实例.

现在我的问题是.如果我使用组件提供程序语法:

@Component({
  selector: 'app',
  providers: [TeamCollection]
}) 

@Component({
  selector: 'player-list',
  providers: [PlayerCollection]
})

会共享同一个玩家集合还是会创建一个新实例?

只要通过bootstrap(.., [ServiceA,ServiceB])方法创建它们即可.

感谢pascal precht http://blog .thoughtram.io/angular/2015/09/17/resolve-service-dependencies-in-angular-2.html

How would I go about injecting one service into another? Let's for example say I have a Collection that requires another Collection (TeamCollection => PlayerCollection). Currently I just create two separate Collections and use something like:

import {PlayerCollection} from "<<folder>>/player";

But this requires me to write my own singleton getInstance code within Typescript for each and every service that I want to be a singleton instance.

What is the correct way to do this? I want to have both singletons within my Components and be able to @Inject one service into another using the constructor syntax, without creating a new instance of the singletons.

class TeamCollection {    
    constructor(@Inject(PlayerCollection): PlayerCollection) {}
}

解决方案

So after re-reading this excellent post by Pascal Precht: http://blog.thoughtram.io/angular/2015/05/18/dependency-injection-in-angular-2.html

And seeing him comment on: http://twofuckingdevelopers.com/2015/04/angular-2-singleton-service/

"Everything injected using Angular 2’s DI is already a Singleton. No need for such a service"

I went testing, and what I now found has both answered my question and made me even more confused about the topic of DI in angular2.

See the following code:

team.ts

import {BaseCollection, BaseModel} from "./base";
import {PlayerCollection} from './player';
import {Injectable, Inject} from "angular2/angular2";

@Injectable()
export class TeamCollection extends BaseCollection {
    playerCollection: PlayerCollection;
    constructor(@Inject(PlayerCollection) playerCollection: PlayerCollection) {
        super();
        this.playerCollection = playerCollection;
    }

    create(data: Object): TeamModel {
        return new TeamModel(data);
    }
}

player.ts

import {BaseCollection, BaseModel} from "./base";
import {Injectable} from "angular2/angular2";

@Injectable()
export class PlayerCollection extends BaseCollection {
    create(data: Object): PlayerModel {
        return new PlayerModel(data);
    }
}

team.spec.ts

/// <reference path="../../typings.d.ts" />

//VERY IMPORTANT TO ALWAYS LOAD THESE
import 'zone.js';
import 'reflect-metadata';
import 'es6-shim';

import {TeamModel, TeamCollection} from "../../app/model/team";
import {PlayerCollection} from "../../app/model/player";
import {Inject, Injector} from "angular2/angular2";

describe('TeamCollection', () => {
  var teamCollection: TeamCollection;
  var playerCollection: PlayerCollection; 
  beforeEach(() => {
      var injector = Injector.resolveAndCreate([
        TeamCollection,
        PlayerCollection
      ]);
      teamCollection = injector.get(TeamCollection);  

      var injectorT = Injector.resolveAndCreate([
        PlayerCollection
      ]);
      playerCollection = injector.get(PlayerCollection);
  });

  it('should have a singleton PlayerCollection shared between all classes within the application', () => {
    console.log(teamCollection.playerCollection.uuId);
    console.log(playerCollection.uuId);
  });  
});

As long as it was the same Injector (var injector) that created both they share the same uuID Though when I use a second injector (var injectorT) the UUIDs are different meaning a new instance is created of the playerCollection.

Now my question would be. If I use the component providers syntax:

@Component({
  selector: 'app',
  providers: [TeamCollection]
}) 

@Component({
  selector: 'player-list',
  providers: [PlayerCollection]
})

Would both share the same player collection or would both create a new instance?

Edit: They do as long as they are created through the bootstrap(.., [ServiceA,ServiceB]) method.

Thanks to pascal precht http://blog.thoughtram.io/angular/2015/09/17/resolve-service-dependencies-in-angular-2.html

这篇关于Angular2“服务"如何将一项服务注入另一项(单例)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆