james watt
james watt

Reputation: 135

Sharing same Observable from a Service in Pages/Components

I'm trying to subscribe the same Observable multiple times but it doesn't work. I've got a Provider that gives me the Observable from AngularFirestore object. This is my provider:

@Injectable()
export class MyProvider {
  private myObservable: Observable<any>;
  constructor(private aFs: AngularFirestore) {
    //retriving some data and putting in myObservable
  }

  getObservable() {
    return this.myObservable;
  }
}

In my myPage.ts I do:

this.mySubscription = this.myProvider.getObservable().subscribe(value => {
  //something that works
});

In another component I do the same but it doesn't give me anything. How I can share an Observable from a service or a provider? I've tried to unsubscribe() it and it works when i pop from my page to the component, when I call the unsubscribe() on the component and then I navigate to my page, the subscribe() doesn't work.

To unsubscribe() in my page I do:

ionViewWillLeave() {
  this.mySubscription.unsubscribe();
}

To unsubscribe() in my component, before I navigate to my page, I do:

myEvent() {
  this.mySubscription.unsubscribe();
  this.navCtrl.push(MyPage);
}

When I pop from MyPage the unsubscribe() seems to work properly because I can see myObservable data in my component. When I try to navigate from my component to MyPage the unsubscribe() seems to doesn't work because I can see nothing. I also tried with debugging but I can't see nothing into the subscribe() in the second case.

I import my provider in the app.module.ts under providers and then I import it in my pages:

MyPage.ts

import { MyProvider } from ..;

The constructor (MyPage.ts):

constructor(private myProvider: MyProvider) {..}

And in my component:

MyComponent.ts

import { MyProvider } from ..;

The constructor (Home.ts)

constructor(private myProvider: MyProvider) {..}

I clarify that MyComponent isn't used in MyPage! I use it in the Home and then I use it to push to MyPage. I'm doing this because I want to show simple data in MyComponent and then I want to push to MyPage that contains the data details.

Easily I want to share the same Observable retrived from a service on a component and on a page, and I want to subscribe() it on both. Is this possible?

Upvotes: 1

Views: 1718

Answers (1)

Vikas
Vikas

Reputation: 12036

If your objective is to multicast the data use RXJS's Subject or BehaviorSubject
Subject acts as a bridge/proxy between the source Observable and many observers, making it possible for multiple observers to share the same Observable execution.
This recommended way of exposing Subjects are using the asObservable() operator.

@Injectable()
export class MyProvider {
  private myObservable=new Subject<any>();
  CurrentData = this.myObservable.asObservable();
  constructor(private aFs: AngularFirestore) {
    //your logic
      this.myObservable.next(value);//push data into observable
  }


}

Page.ts

this.mySubscription = this.myProvider.CurrentData.subscribe(value => {
      //something that works
    });

Using Behavior Subject

 @Injectable()
    export class MyProvider {
      private myObservable=new BehaviorSubject<any>('');
      CurrentData = this.myObservable.asObservable();
      constructor(private aFs: AngularFirestore) {

      }

     getData(myParam): void { 
       someasynccall.pipe(map(),filter()).
          subscribe(value=>this.myObservable.next(value))


    }

Page.ts

this.myProvider.getData(param);
this.mySubscription = this.myProvider.CurrentData.subscribe(value => {
      //something that works
    });

Subject vs BehaviorSubject

LiveDemo

Upvotes: 4

Related Questions