Angular2 “Services” how to @inject one service into another (singletons)?

后端 未结 3 1215
庸人自扰
庸人自扰 2020-12-28 14:20

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). Cu

相关标签:
3条回答
  • 2020-12-28 14:39

    I found that another way of having a singleton service is by creating the singleton pattern with a getInstance() method that calls the constructor, then you don't inject your service to the component constructor, but just reference it as a static class. You can check sample code in here:

    Access key data across entire app in Angular 2 & Ionic 2

    Look for my answer, I think its the second in the page. If it works for you I would appreciate if you could up-vote it. Thanks.

    0 讨论(0)
  • 2020-12-28 14:48

    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

    0 讨论(0)
  • 2020-12-28 14:56

    What you need to make sure of is the following:

    You can only inject the service once you have "provided" the service. When doing this in a @component its easy because you have the providers [ .... ] statement.

    When you want to do this for a service you do not have the providers:[].... so the only place you can do this is during bootstrap time where you need to specify the service in

    boostrap(app, [
    
    PlayerCollection,
    Other,
    More Services...
    
    
    
    ]
    

    If you dig in the documentation it specifically says you need to do it this way.

    0 讨论(0)
提交回复
热议问题