Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular and rxjs - do I need connect or refCount?

Tags:

angular

rxjs

Basically, I asked about reusing the data from observables yesterday, then I asked around other places as well and read some more then I figured, why not just hold an observable and manipulate the data with map operators.

So I'm making just one HTTP request, store the observable to some variable and manipulate it there. The code works, but I'm not sure if I'm using .publishReplay(1).refCount() correctly, or should I use connect? Or, do I even need any of that? Also, is there any possible memory leak that could come out of this service?

Here's the code to service:

@Injectable()
export class UsersApiService {

  private readonly baseUrl: string = 'https://reqres.in/api/users';
  resource$: Observable<any>;

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

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

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

}

And the working example: http://plnkr.co/edit/3S8iKbvrrGOj9netd8sM?p=preview

like image 580
uglycode Avatar asked Dec 13 '17 22:12

uglycode


People also ask

What is refCount RxJS?

Descriptionlink. Internally it counts the subscriptions to the observable and subscribes (only once) to the source if the number of subscriptions is larger than 0. If the number of subscriptions is smaller than 1, it unsubscribes from the source.

What is the key difference between share and shareReplay?

In contrast to share , shareReplay exposes a ReplaySubject to subscribers. ReplaySubject(1) is very similar to a BehaviorSubject .

What does RxJS share do?

RxJS share() operator is a multicasting operator which returns a new observable that shares or multicasts the original observable. As long as there is at least one subscriber, this observable will be subscribed and emitting data. When all subscribers have unsubscribed, it will unsubscribe from the source observable.

What is pipe operator in RxJS?

A Pipeable Operator is a function that takes an Observable as its input and returns another Observable. It is a pure operation: the previous Observable stays unmodified. A Pipeable Operator is essentially a pure function which takes one Observable as input and generates another Observable as output.


1 Answers

I'm not sure if I'm using .publishReplay(1).refCount() correctly

Yes, you are. You can also use shareReplay(1) instead.

or should I use connect?

refCount() already connects for you when the first subscriber comes along (and disconnects when all observers have unsubscribed).

do I even need any of that

If you want to hold it as an observable, yes. Otherwise you will query the backend over and over again. You could, however, of course also just memorize the last emission:

private resource: Observable<IUserDetails[]>;

constructor(http: HttpClient) {
    this.http.get(/* … */).subscribe(data => this.resource = data);
}

getUserById(id: number): IUserDetails {
    return this.resource.find(x => x.id === id);
}

Also, is there any possible memory leak that could come out of this service?

No, because HttpClient completes its return observable, which means the source of your multicasted observable is disconnected.

like image 125
Ingo Bürk Avatar answered Sep 28 '22 07:09

Ingo Bürk