'Services and fetching data only once

I just to make sure this is a good approach to what I am trying to do. I have a component and a service. The service is responsible for holding data for the component, as well as fetching it from an http api. Here's a snippet from the service:

  private _sessionDirectories: string[] | null = null;
  private sessionDirectories: ReplaySubject<string[]> = new ReplaySubject<string[]>(1);
  sessionDirectories$ : Observable<string[]> = this.sessionDirectories.asObservable()

  constructor(private getService: GetService,
    private apiService: ApiEndPointsService) { }


  hasSessionDirectories() : boolean {
    return this._sessionDirectories !== null; 
  }

  fetchSessionDir() : Observable<boolean> {
    return this.getSessionDir().pipe(
      tap(o => {
        this._sessionDirectories = o;
        this.sessionDirectories.next(o);
      }),
      map(() => true),
      catchError(()=> of(false))
    );
  }

  private getSessionDir() : Observable<string[]> {
    return this.getService.get(this.apiService.getGetSessionDir()).pipe(
      map((o : any) => o.directories),
      shareReplay(1),
    );
  }

And here is a snippet from the component:

  directories$: ReplaySubject<string[]> = new ReplaySubject<string[]>(1);

  constructor(private sessionService: SessionService,
    private router: Router,
    private errorService: ErrorService) { 
  }

  isLoaded : boolean = false;
  ngOnInit(): void {
    this.sessionService.sessionDirectories$.pipe(take(1)).subscribe(o =>{
            console.log(o);
            this.directories$.next(o);
            this.isLoaded = true;
      });

    if (!this.sessionService.hasSessionDirectories()) {
      this.sessionService.fetchSessionDir().subscribe(o => {
        if (!o) {
          this.errorService.updateMessage("Could not load sessions");
          this.router.navigate(['error']);
        }
      });
    }
  }

So my questions are:

  1. Given the way that I've written it, I guess using shareReplay(1) in getSessionDir() is kinda of pointless? Given that it is subscribed to only within the service (private method), and that there is only 1 subscriber as well.

  2. Is the way that I have "tunnelled" up the error to the component a good way to do it?

  3. That I've got _sessionDirectories, sessionDirectories, and sesssionDirectories$ just doesn't seem right to me. I introduced _sessionDirectories so that I can create a hasSessionDirectories() method, so that I only fetch once in the component. Ideally I'd have checked whether sessionDirectories$ has any values, and if so then don't do it. If I subscribe to this.sessionService.sessionDirectories$ within the constructor, the call back of the subscribe method isn't called - I guess because the "stream" of sessionDirectories$ is still empty. Ideally I would have done something like:

this.sessionService.sessionDirectories$.subscribe(o => {
if (!o) {
 // code to fetch for the first time, but this isn't executed because sessionDirectorie$ is empty...
}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source