tegoli5101
tegoli5101

Reputation: 13

Cache emited value when using async pipe to be able to filter out future emits

I'm trying to cache the emitted value of an observable to filter out irrelevant future emits.

I have a route:

{ path: "user/:id/:type", component: UserComponent }

Within that component i'm getting the ActivatedRoute params, switchMap to the actual http call, and using async pipe on template to show the user details.

user$: Observable<User>;

ngOnInit() {
    this.user$ = this.route.params.pipe(
       switchMap(params => {
         return this.http.getUser(params.id)
       })
    );
}

in the template it self:

<div *ngIf="user$ | async as user"> 
   <span>{{ user.id }}</span>
   <span>{{ user.name }}</span>
</div>

I would like to filter out this.route.params values, if the route changes but the :id param stays the same.

I was thinking something like

user$: Observable<User>;

ngOnInit() {
    this.user$ = this.route.params.pipe(
       withLatestFrom(this.user$ || Observable.from({})),
       filter( ([params, user]) => {
           return (params.id !== user.id); // filter if params id equals to last fetched user
       }),
       switchMap(params => {
         return this.http.getUser(params.id)
       })
    );
}

but withLatestFrom comes up null. i would like to avoid caching it using a tap operator, and just come up with a clean alternative, somewhere like the road i tried to take. what am i missing ?

Upvotes: 1

Views: 694

Answers (1)

Barremian
Barremian

Reputation: 31125

To compare the value only with the last emission, you could use RxJS pluck operator to select the id property and distinctUntilChanged operator to ignore the notifications until the id is changed.

Try the following

ngOnInit() {
    this.user$ = this.route.params.pipe(
       pluck('id'),
       distinctUntilChanged(),
       switchMap(id => {
         return this.http.getUser(id)
       })
    );
}

Or to ignore all the duplicates and trigger the HTTP request only for distinct ids, you could RxJS distinct operator.

ngOnInit() {
    this.user$ = this.route.params.pipe(
       distinct(params => params['id']),
       switchMap(params => {
         return this.http.getUser(params.id)
       })
    );
}

Upvotes: 1

Related Questions