Angular2 Observable BehaviorSubject service not working

17,633

Solution 1

Every time you emit a value, you should create a new object instead of emitting the same mutated object. That will protect you from change detection issues. It'd be better to always assign a new Object to this.keys when you change it though.

this.data.next([...this.keys]);

You can use asObservable() here

public getData(): Observable<number[]> {
  return this.data.asObservable();
}

Also check for what Günter Zöchbauer said. Are you providing the service as a singleton?

Solution 2

I faced the same issue at some point. It's likely the reason is that your service is not a singleton, i.e. that every subscriber gets a new instance. Contrary to Angular 1, in A2 services are not singletons.

If you want to have one instance of the service shared by multiple services/components, put it in providers of your parent @Component or @NgModule.

@NgModule({
  declarations: [],
  imports: [],
  bootstrap: [AppComponent],
  providers: [DataService]
})
export class AppModule {
}
Share:
17,633

Related videos on Youtube

kjoetools
Author by

kjoetools

Updated on June 26, 2022

Comments

  • kjoetools
    kjoetools almost 2 years

    I'm trying to create my own observable service but after i get the initial data from the service, any updates to the service aren't propagated to any subscribers. Service looks like this:

    import { Injectable } from '@angular/core';
    import { Observable, BehaviorSubject } from 'rxjs/Rx';
    
    @Injectable()
    export class DataService {
      keys : number[] = [4,5,1,3,2];
      private data :BehaviorSubject<number[]> = new BehaviorSubject(this.keys);
    
      constructor() {};
    
      public setKey(i:number, val:number) :void {
        this.keys[i]=val;
        this.data.next(this.keys);
      }
      public getData() :Observable<number[]> {
        return new Observable(fn => this.data.subscribe(fn));
      }
      public getKeys() :number[] {
        return this.keys;
      }
    }
    

    the component using the service gets the initial data just fine. that component gets its data in the constructor:

    constructor(public dataService: DataService) {
        dataService.getData().subscribe(data => {
          console.log("Gotcha!");
          this.data.datasets[0].data = data)
        });
    };
    

    which gives one Gotcha in the console log. But after updating the data with setKey(2,3) somewhere else, i was expecting the this.data.next(this.keys); to send data to all subscribers and data would be updated inside that component accordingly. but no data is sent to the subscribers..

    i thought i figured the Observables out but please dont be friendly if i'm missing the point here ;) any pointers in the right direction will be greatly appreciated!

    • Günter Zöchbauer
      Günter Zöchbauer over 7 years
      Sounds like you are providing the service more than once which leads to different components getting different instances.
    • webmaster
      webmaster over 7 years
      What should be the approach when working in modules. I have a similar service. Some of my components (in different modules) subscribe on an observable in my auth service and receive data when it changes but others don't receive data. Eg. when my login (btn) component emits next on the observer the login components sees the change but my header & sidebar components don't while they are also subscribed, I think it has to do with lazy loading or so, or cache, or some parent child problem.. pff
    • jminuscula
      jminuscula over 6 years
      @GünterZöchbauer thanks for this! I was providing the service both as part of the component and in the parent module. It was driving me crazy!
    • Tasos Anesiadis
      Tasos Anesiadis about 5 years
      @GünterZöchbauer I literally lost hours on this. Thank you so much.
    • BALAJI RAJ
      BALAJI RAJ almost 4 years
      @GünterZöchbauer. Thanks a lot. i'm new to Angular, it helped me to fix the issue quickly.
  • kjoetools
    kjoetools over 7 years
    that works like a charm! (after i corrected my rookie mistake that Gunter pointed out coughcough*)..
  • kjoetools
    kjoetools over 7 years
    i had it in bootstrap but also in the providers inside the components. removing it from made it all work :) tnx! wondering though, i was on RC.4 and had no @NgModule. You're referring to RC.5 probably? when i upgraded i got all kinds of weird traceur messages in the console and it broke my application (following the angular2 site's upgrade path). have you tried their upgrade path and got away with it?
  • Konrad Garus
    Konrad Garus over 7 years
    I only started with RC5, so I am not really familiar with the upgrade path and its quirks. Lucky me, I guess. :-)
  • Emil Rosenius
    Emil Rosenius almost 7 years
    After almost 4 hours of trying literally every single solution, this finally solved all of my problems. Thank you so much
  • bkdraper
    bkdraper about 5 years
    this one was my solution. 3 years later in 2019 and still not one BehaviourSubject tutorial i went through mentioned anything about the singleton problem or the proper place to set the service provider like Konrad mentions here. Thanks Konrad.
  • Wilt
    Wilt over 4 years
    How to deal with a long living object that is not supposed to be changed, say a object reflecting a REST resource that mutates over time. Is there some workaround? I want to anyway update my view listening to changes emitted by a BehaviorSubject exactly for such a case.
  • Kshri
    Kshri almost 4 years
    Do we still need to do this if in the service its mentioned as @Injectable({providedIn: 'root'}) ? plz help!