首页 > 解决方案 > @ngrx 选择器并行发射两次

问题描述

我有一个非常简单的选择器

export const isLoading = createSelector(
  state => state.$loading
);

和两个动作StartLayoutNavigationActionEndLayoutNavigationAction只是$loading相应地设置标志。我调用这些函数一次,我的操作被记录下来:

ACTION – [Layout] Start navigation StartLayoutNavigationAction {layout: "login", type: "[Layout] Start navigation"}
ACTION – [Layout] End navigation EndLayoutNavigationAction {type: "[Layout] End navigation"}

所以人们会假设选择器会在第一个动作被调用时发出一次,在第二个动作被调用时发出一次。中间没有任何动作。

但:

选择器似乎并行发出两次。我管道如下:

layoutLoading$: Observable<boolean> = this.store.pipe(
  select(isLoading),
  distinctUntilChanged((x, y) => {
    console.log("Comparison:", x, y);
    return x === y;
  }),
  tap(value => console.log("New val:", value))
);

这是输出:

ACTION – [Layout] Start navigation StartLayoutNavigationAction {layout: "login", type: "[Layout] Start navigation"}
Comparison:  false true
New val: true
Comparison: false true
New val: true
ACTION – [Layout] End navigation EndLayoutNavigationAction {type: "[Layout] End navigation"}
Comparison: true false
New val: false
Comparison: true false
New val: false

我有什么问题吗?这是预期的行为吗?

标签: rxjsngrx

解决方案


根据评论

您确定 layoutLoading$ 只有一个订阅吗?例如,您有多个异步管道、多个组件实例。- @Buggy

const source$ = of(1).pipe(
  tap(value => console.log("New val:", value))
);

source$.subscribe();
source$.subscribe();
// 1
// 1

好的,你是对的,我有两个异步订阅。我不知道这对每个订阅都有效。所以当我想对不同的变化做出反应时(除了异步管道),我需要第二个可观察的管道,对吧?- @Giacomo Voß

是的,如果我理解正确:

source$
  .pipe(distinctUntilChanged(fn))
  .subscribe(/* do something */)

推荐阅读