简体   繁体   中英

Angular Shared Service - Subscribe passes undefined to component

I am attempting to implement the singleton design pattern by using a shared service so that all components are able to receive the updated global variable provided by the service.

The result is that it will update without issue when called from app component, but no component receives the value when subcribing to:

colorString$ = this.colorSource.asObservable();

The method used to subscribe which is not returning a value:

  constructor( private sharedSer : SharedColorService ) {
    sharedSer.Update(this.myColor);
  }

This is the service:

import {Injectable} from '@angular/core';
import { Subject }   from 'rxjs/Subject';

@Injectable()
export class SharedColorService {

  // Observable string source
private colorSource = new Subject<string>();

// Observable string stream
colorString$ = this.colorSource.asObservable();

// Service message commands

Update(input:string) {
   this.colorSource.next(input);
   console.log("Service Color: " + input);
}
}

This is the app.component:

import { Component, OnInit } from '@angular/core';
import {SharedColorService} from './sharedColor.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  colors = ["#31b0d5", "#d55631", "#d531b0", "#31d556"]
  myColor = this.colors[Math.floor(Math.random()*this.colors.length)];

  constructor( private sharedSer : SharedColorService ) {
    console.log("I can log");
    console.log("App Color: " + this.myColor);
    sharedSer.Update(this.myColor);
  }
  }

This is the component which the app component loads:

app.component.html:

<h1>APP: {{myColor}}</h1>
<app-navigation></app-navigation>

navigation.component

import { Component, OnInit, Injectable } from '@angular/core';
import {SharedColorService} from '../sharedColor.service';
@Component({
  selector: 'app-navigation',
  templateUrl: './navigation.component.html',
  styleUrls: ['./navigation.component.css'],
})

export class NavigationComponent{
  myColor: string;
  errors;
  constructor(private _sharedService: SharedColorService){
    console.log("I AM TRYING TO SUBSCRIBE");
    this._sharedService.colorString$.subscribe(
     result => {
        console.log('Navigation received result: ', result);
        this.myColor = result;
      });
        console.log('Navigation after subscribe: ', this.myColor)
  }
}

And finally I have a router outlet, which loads from navigation:

navigation.component.html

<a class="col-sm-2" routerLink="/about" routerLinkActive="active">About</a>
<router-outlet></router-outlet>

about.component

import { Component, OnInit } from '@angular/core';
import {SharedColorService} from '../sharedColor.service';

@Component({
  selector: 'app-about',
  templateUrl: './about.component.html',
  styleUrls: ['./about.component.css']
})
export class AboutComponent implements OnInit {

myColor: string;
constructor(private _sharedService: SharedColorService){}

ngOnInit() {
  this._sharedService.colorString$.subscribe(
    data => {
      this.myColor = data;
          console.log("About received color: " + this.myColor + " Data: " + data );
    });
}
}

The output of console with all of the logging when loading the page is:

I can log
app.component.ts:15 App Color: #31d556
sharedColor.service.ts:16 Service Color: #31d556
navigation.component.ts:15 I AM TRYING TO SUBSCRIBE
navigation.component.ts:21 Navigation after subscribe:  undefined

When accessing about, it is not called to subscribe either - I don't yet understand the lifecycle of the router outlet regarding OnInit and its constructors.

It now works using a Behavior Subject instead of a subject:

import {Injectable} from '@angular/core';
import { Subject }  from 'rxjs/Subject';
import {BehaviorSubject} from 'rxjs/BehaviorSubject';

@Injectable()
export class SharedColorService {

  // Observable string source
private colorSource: BehaviorSubject<string>= new BehaviorSubject<string>("#d55631");

// Observable string stream
colorString$ = this.colorSource.asObservable();

// Service message commands
Update(input:string) {
   this.colorSource.next(input);
   console.log("Service Color: " + input);
}

}

Console.log

app.component.ts:14 I can log
app.component.ts:15 App Color: #31b0d5
sharedColor.service.ts:17 Service Color: #31b0d5
navigation.component.ts:13 I AM TRYING TO SUBSCRIBE
navigation.component.ts:16 Navigation received result:  #31b0d5
navigation.component.ts:19 Navigation after subscribe:  #31b0d5
core.es5.js:3025 Angular is running in the development mode. Call 
about.component.ts:18 About received color: #31b0d5 Data: #31b0d5

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM