2

I have a back-end service that returns user details that I need on multiple Angular components. My problem is that it's obviously been called multiple times. Here is my get request:

getUser(): Observable<User> {
  if (this.user) {
    return Observable.of(this.user);
  } else {
    return this.http
      .get<User>(BACKENDPATH)
      .map((user: User) => new User().deserialise(user))
      .do((user) => {
        this.user = user;
        console.log(this.user.getUserName());
        return this.user;
      });
   }
}

I have tried the following methods after the get part of the function but none have worked:

  • .publishReplay(1).refCount()
  • .shareReplay()
  • .shareReplay(1)

These methods have worked for others online so I'm guessing that I am doing something wrong with the implementation of them but I can't figure out what.

Shane Watson
  • 133
  • 1
  • 12
  • I guess it the request is sent many time because, before hitting the `this.user = user;` line, many components have called the method `getUser()`. Can you confirm? – Picci Jul 06 '18 at 09:52
  • @Picci Yes that's why but I believe that one of the purposes of the methods that I've posted is so that it won't make a get request multiple times – Shane Watson Jul 06 '18 at 10:02
  • Your question is answered is here: https://stackoverflow.com/questions/51044291/using-sharereplay1-in-angular-still-invokes-http-request/51044495#51044495 – siva636 Jul 06 '18 at 10:05
  • @ShaneWatson The question is how you use `getUser()`. Do you call it multiple times? Or you make a single call then call `subscribe()` multiple times? – martin Jul 06 '18 at 10:06

2 Answers2

3

You are creating a new stream with every getUser() call.
Solution: Make one Http request and work with cached/stored data. Use Below Approach

export class SharedService {

    data$: Observable<User>;
    getUser(): void {

        this.data$ = this.http
            .get<User>(BACKENDPATH)
            .map((user: User) => new User().deserialise(user))
            .do((user) => {
                this.user = user;
                console.log(this.user.getUserName());
                return this.user;
            }).shareReplay(1);
    }

    getData(): Observable<User> {
        return this.data$;
    }
}

Component:

this.service.getData().sub(...)
Vikas
  • 11,859
  • 7
  • 45
  • 69
0

Vikas helped figure out this issue. This is my code now:

userData: Observable<User> = this.http
  .get<User>(BACKENDPATH)
  .map((user: User) => new User().deserialise(user))
  .shareReplay(1);

getUser(): Observable<User> {
  return this.userData;
}
Shane Watson
  • 133
  • 1
  • 12
  • 1
    If you are gonna invoke your method multiple times you would end up creating new stream with every invocation i.e multiple request will be triggered Better make one request and work with cached data. – Vikas Jul 06 '18 at 10:19
  • Hi @Vikas I understand now and have updated by comment, it works. What do you think? – Shane Watson Jul 06 '18 at 13:02