使用异步管道时缓存发出的值,以便能够过滤掉未来的发出

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

我正在尝试缓存 observable 的发射值以过滤掉不相关的未来发射。

我有一条路线:

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

在该组件中,我正在获取 ActivatedRoute 参数,switchMap 到实际的 http 调用,并在模板上使用 async 管道来显示用户详细信息。

user$: Observable<User>;

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

在自己的模板中:

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

如果路由发生变化但 :id 参数保持不变,我想过滤掉 this.route.params 值。

我在想

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)
       })
    );
}

withLatestFrom 出现空值。 我想避免使用 tap 运算符缓存它,只是想出一个干净的替代方案,就像我试图走的路一样。我错过了什么?

要仅将值与最后一次发射进行比较,您可以使用 RxJS pluck 运算符来 select,id 属性 和 distinctUntilChanged 运算符来在 id 更改之前忽略通知。

尝试以下方法

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

或者要忽略所有重复项并仅针对不同的 id 触发 HTTP 请求,您可以使用 RxJS distinct 运算符。

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