Search code examples
javascriptangularcomponentsobservers

How to share service data between components correctly in Angular 2


I want to create a service to get data from .json file once and share it to multiple subscribers. But now with my solution number of requests to get data from .json file equals to a number of a subscibers for my service.

getconfig.service.ts

import {Injectable} from 'angular2/core';
import {Http, Response} from "angular2/http";

@Injectable()
export class ConfigService {
    config: any;
    http: Http;

    constructor(http: Http) {
        this.http = http;
        console.log('Inside service');
        this.config = this.http.get('/config.json');
    }

}

robotui.component.ts

...
import {ConnectionService} from '../services/connection.service';

@Component({
  ...
  providers: [HTTP_PROVIDERS, ConfigService, ConnectionService]
  ...
})

constructor(private _configService: ConfigService) {
  this._configService.config.subscribe((observer) => {
    console.log('Subscribe in RobotUI component', JSON.parse(observer._body));
  });
}

actual.photo.component.ts

import {Component} from 'angular2/core';
import {ConfigService} from '../services/getconfig.service';

@Component({
  ...
  providers: [ConfigService]
})

export class ActualPhotoComponent {

  constructor(private _configService: ConfigService) {
    this._configService.config.subscribe((observer) => {
      console.log('Subscribe in ActualPhoto component', JSON.parse(observer._body));
    });
  }

}

When i run it in my console i see:

enter image description here

So, there is get request for each subscibers. I want a solution when i get config.json file only once, save this info in a service and share it with multiple subscibers.


Solution

  • That's because

    @Component({
      ...
      providers: [ConfigService]  //<--- this creates service instance per component
    })
    

    To share data among controllers/components and to create single instance only, you have to inject your service into bootstrap function.

    import {ConfigService } from './path to service';
    
    bootstrap('AppCompoent',[configService])  //<----Inject here it will create a single instance only
    

    In subscribing component,

    robotui.component.ts

    ...
    import {ConfigService} from '../services/getconfig.service';  //<----- Note this line here....
    import {ConnectionService} from '../services/connection.service';
    
    @Component({
      ...
      ...  // No providers needed anymore
      ...
    })
    
    constructor(private _configService: ConfigService) {
      this._configService.config.subscribe((observer) => {
        console.log('Subscribe in RobotUI component', JSON.parse(observer._body));
      });
    }
    

    actual.photo.component.ts

    import {Component} from 'angular2/core';
    import {ConfigService} from '../services/getconfig.service';
    
    @Component({
      ...
      ...  // No providers needed anymore...
    })
    
    export class ActualPhotoComponent {
    
      constructor(private _configService: ConfigService) {
        this._configService.config.subscribe((observer) => {
          console.log('Subscribe in ActualPhoto component', JSON.parse(observer._body));
        });
      }
    
    }
    

    This is what you should do.