2

I have an AuthService that fetch an Observable<auth> data from Firebase and put it in a public variable auth$.

Somewhere in my app, I need multiple components to access this auth$ value to check its content.

I'm currently just doing this.authService.auth$.subscribe(auth => this.auth = auth) in components.

  1. Does it mean that I'm executing the fetch data from Firebase multiple times?

  2. If yes, should I define auth$ as a Subject/BehaviorSubject, subscribe in the service and push data with .next?

Tom
  • 785
  • 10
  • 26
  • FIrebase has some internal caching, so it shouldn't be a problem. You can check network traffic in DevTools > Network > WebSockets... – Sasxa Nov 17 '16 at 09:24
  • OK that's good to know about Firebase, I'll check this out. But what about an http call? (something without caching) – Tom Nov 17 '16 at 09:27
  • You can use [`share()`](http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-share) operator, `this.authService.auth$ = Observable.of('whatever').share()` and it should be shared among all subscriptions... – Sasxa Nov 17 '16 at 09:29
  • Ok cool thanks for your answer. – Tom Nov 17 '16 at 09:33
  • Any update on this. I have another thread looking into this as well: http://stackoverflow.com/questions/41755912/how-to-easily-convert-or-assign-an-observable-to-a-behavior-subject-so-other-co I use behavior subject for the firebase auth so it's multicast enabled. But now I want the userInfo to be multicast enabled but I have no idea how to reproduce the same pattern - sharing data across my angular 2 app. – Hugh Hou Jan 20 '17 at 18:53

1 Answers1

5

Default an observable is not multicast enabled. This means that multiple subscriptions will generate their own stream. Since you do not want to have to re-fetch the authentication credentials per subscription you need to make your original stream multicast-compatible. This is done using for example the share() operator, which will make the stream hot upon the first subscription and internally stores a refcount for all following subscriptions.

Since subscriptions which are late to the party will not automatically get the previous emitted values when the stream became hot we need to build in functionality to replay emitted values.

Both of these requirements are combined in the shareReplay() operator which lets your multicast the latest n values.

So your code would look like this:

const authStream = this.authService.auth$.shareReplay(1);

// component 1
const myAuthDisposable = authStream.subscribe(auth => this.auth = auth)

// component 2
const myAuthDisposable = authStream.subscribe(auth => this.auth = auth)
Mark van Straten
  • 9,287
  • 3
  • 38
  • 57
  • 1
    Ok thanks! I didn't know `shareReplay()`. It seems like it has been removed. It's saying [here](http://stackoverflow.com/questions/35246873/sharereplay-in-rxjs-5) that it should be replaced with `.publishReplay(1).refCount()`. Do you agree? – Tom Nov 29 '16 at 10:41
  • The long discussion in the github issue seems to say that `.publishReplay(1)` behaviour will be the same in rxjs5 as in rxjs4 so using in combined with `refCount()` would seem to work. Have not tested it myself though. – Mark van Straten Nov 30 '16 at 08:39