带过滤器的ngrx选择器

Dav*_*vid 7 ngrx angular

我在一个Angular应用程序中使用@ngrx,我想抽象一个我已经拥有的循环模式.

我的州通常由许多州组成,如下所示:

myState: {
  data: any
  isLoading: boolean
  isLoaded: boolean
}
Run Code Online (Sandbox Code Playgroud)

所以我最终在代码中做的是订阅它但我只想在状态已加载时收到通知.

this.store
  .select(state => state.myState)
  .filter(myState => myState.isLoaded)
  .map(myState => myState.data)
  .do(data => do_whatever_I_need_to_do)
  .subscribe();
Run Code Online (Sandbox Code Playgroud)

这对我有用,但我想知道我是否可以简化前3个操作符,因为它们非常复发.

通过使用选择器,我可以创建这样的东西

const selectMyState = (state) => state.myState;

export const getData = createSelector(selectMyState, state => state.data)
Run Code Online (Sandbox Code Playgroud)

然后像这样使用它

this.store
  .select(getData)
  .do(data => do_whatever_I_need_to_do)
  .subscribe();
Run Code Online (Sandbox Code Playgroud)

但后来我错过了过滤器部分,所以即使我的数据尚未加载,我也可能从中获取流事件.

有没有办法将这个丢失的过滤器包含在observable中?我知道createSelector有一个函数作为param,所以我可以在那里做一些代码,但我不知道如何使用它来过滤不是数据,而是事件本身.

有任何想法吗?谢谢!

小智 6

该示例来自 ngrx.io

假设您有 selectValues 选择器,并且您想要过滤使代码可重用的值。

import { select } from '@ngrx/store';
import { pipe } from 'rxjs';
import { filter } from 'rxjs/operators';

export const selectFilteredValues = pipe(
 select(selectValues),
 filter(val => val !== undefined)
);

store.pipe(selectFilteredValues).subscribe(/* .. */);
Run Code Online (Sandbox Code Playgroud)


byg*_*ace 5

对于我想重用流的一部分的那种场景,我创建了一个函数,该函数接受存储作为参数并对其执行一些操作。下面是一个例子:

const selectMyState = (state) => state.myState;
export const getData = createSelector(selectMyState, state => state.data)
export const getDataWhenLoaded = (store) => {
    return store.select(getData)
        .filter(myState => myState.isLoaded);
};
...
getDataWhenLoaded(this.store).subscribe(...);
Run Code Online (Sandbox Code Playgroud)

至于使用createSelector函数的最后一个参数,您可以根据需要。在文档中,它提到传递给由创建的记忆化选择器的相同状态createSelector不会重新计算投影。调用时将返回相同的值。我找不到这方面的文档,但通过测试我注意到,如果投影结果与前一个值相同,那么如果订阅已经收到前一个值,则不会发出它。与 rxjs 操作符类似的行为distinctUntilChanged。我没有时间深入研究他们的源代码以了解在哪里/如何/为什么。

因此,在某些情况下,您可以在投影参数(最后一个)中为createSelector. 下面是一个例子:

export const getActive = createSelector(selectMyData, state => state.data.filter(x => x.isActive));
Run Code Online (Sandbox Code Playgroud)