Angular - reusing an observable for different queries This is just a dummy example, but in my real world application I get a lot of data from the web API and I'd like to manipulate it on the client's side. So, I kind of stored the observable I get from the HTTP request locally and change the values with map:

@Injectable()
export class UsersApiService {

  private readonly baseUrl: string = 'https://reqres.in/api/users';
  resource$: Observable&lt;any&gt;;

  constructor(private http: HttpClient) {
    this.resource$ = this.http.get&lt;IUserDetails[]&gt;(this.baseUrl).pipe(
      tap((data) =&gt; {
        console.log('"getUsers" successfully called!');
      }),
      map((data: any) =&gt; {
        return data.data;
      })
    ).publishReplay(1).refCount();
  }

  getUsers(): Observable&lt;IUser[]&gt; {
    return this.resource$.pipe(
      map((data: IUserDetails[]) =&gt; {
        return &lt;IUser[]&gt;data.map((u) =&gt; {
          return {
            id: u.id,
            name: `${u.first_name} ${u.last_name}`
          };
        });
      })
    );
  }

  getUserById(id: number): Observable&lt;IUserDetails&gt; {
    return this.resource$.pipe(
      map((data) =&gt; {
        return &lt;IUserDetails&gt;data.find(x =&gt; x.id === id);
      })
    );
  }

}


Here's an example plunker

Is this the correct approach at reusing an observable? What would be better? Am I creating any memory leaks and what are the general drawbacks of my approach? Thanks!
There's nothing (obviously) wrong with your code. You deal with observables the efficient way, IMO. Cache is good. The fact you're constructing a "base" observable in constructor without subscribing to it there is good as well...

There are only a few things I can point out:


Design: Be careful with caching, if your user information changes often, the cache may bite you back. You may want to implement some kind of cache invalidation policy.
Design: If your system has thousands of users, you may want to not load all of them into memory at once. That would require your API support pagination though. If the users are few, it's totally okay to do what you're doing, I think.
RxJs: not sure why pipe() and tap() are used the way are used. I think, it's easier to use do() and map() as shown in the code below. Chaining looks much more readable (as "step-by-step" explanation of how the data is transformed into the desired result).
Idioms: TypeScript is all about types. Do specify a known type when possible instead of using any. E.g. Observable&lt;IUserDetails[]&gt; is better than Observable&lt;any[]&gt;.
Style: Variable naming is important. Do not use one-letter names (u), they are pure evil. Names like data are also evil, in your case it's better to call it response. The resource$ can probably be nicer to the reader if called userDetails$. You get the idea.




@Injectable()
export class UsersApiService {

  private readonly baseUrl: string = 'https://reqres.in/api/users';
  userDetails$: Observable&lt;IUserDetails[]&gt;;

  constructor(private http: HttpClient) {
    this.userDetails$ = this.http
      .get&lt;IUserDetails[]&gt;(this.baseUrl)
      .do(response =&gt; console.log('"getUsers" successfully called!'))
      .map(response =&gt; response.data)
      .publishReplay(1)
      .refCount();
  }

  getUsers(): Observable&lt;IUser[]&gt; {
    return this.userDetails$
      .map(userDetailsList =&gt;
        userDetailsList.map(userDetails =&gt;
          &lt;IUser&gt;{ id: userDetails.id, name: `${userDetails.first_name} ${userDetails.last_name}` }
        )
      );
  }

  getUserById(id: number): Observable&lt;IUserDetails&gt; {
    return this.userDetails$
      .map(userDetailsList =&gt; &lt;IUserDetails&gt;userDetailsList.find(userDetails =&gt; userDetails.id === id));
  }
}