简体   繁体   中英

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 ?

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 id s, you could RxJS distinct operator.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM