1

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?

james watt
  • 175
  • 1
  • 12

1 Answers1

4

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

Vikas
  • 11,859
  • 7
  • 45
  • 69
  • How I can do if i want to make a call with parameters? I want currentData that depends on parameter I pass to the Provider. Like `getData(myParam): Observable { //dothings like filter or map; myObservable.subscribe(value => { this.currentData.next(value) }); return this.currentData.asObservable(); }` – james watt Jun 18 '18 at 18:53
  • are you making an `Http` call? – Vikas Jun 18 '18 at 18:56
  • I don't understand your requirement fully but you cannot return a value from `subscribe` callback you are working with async programming you need to wait until your subscription is resolved and then take appropriate action – Vikas Jun 18 '18 at 19:12
  • 1
    I have updated my code and provided a wroking stackblitz have a look – Vikas Jun 18 '18 at 19:13
  • Your code is right, i was thinking something like that, but the behaviour I aspected is different. The behaviorSubject 'pass' me a different Observable every time and with the next method I add observables, so every time I add something I must add .next([]) before because I can visualize the old values in the new call. – james watt Jun 19 '18 at 14:23