Angular 2 RxJS过滤到新的可观察

时间:2017-03-06 07:59:14

标签: javascript angular rxjs observable rxjs5

我对RxJS很新(使用5.1.1),并尝试使用angular-redux / store在我的Angular 2 applciation中理解它。

我已经设置了商店,并努力在我的应用程序中获取我的州的不同部分。

现在,我试图将已加载属性设置为true的AppParts:

我的州:

export interface IAppState extends IRootState{
  theme: Theme;
  config: IConfig;
  mainSubTitle: string;
  appParts: AppPart[];
}

选择:

@select(state => state.app.appParts) appParts$: Observable<AppPart>;

现在,我试图从这个可观察的角度获取一个过滤的数组:

loadedAppParts = [];

ngOnInit() {
  this.appParts$.filter(a => a.loaded).subscribe(a => { console.log(a); this.loadedAppParts.push(a); });
}

但是,这会返回一个空数组。我希望能够使用异步管道来获取“已加载的AppPart”。如果可能的话,我也尝试过以下方法:

loadedAppParts: Observable<AppPart> = new Observable<AppPart>();
ngOnInit() {
  this.loadedAppParts = this.appParts$.filter(a => a.loaded);
}

那么,如何从我的Observable状态中获取过滤后的数组或observable?

忘记添加我的Rootstate:

export interface IRootState { };

和我的初始状态:

export const INITIAL_STATE: IAppState = {
  theme: THEMES.LightGreyBlue,
  config: <IConfig>{
    data: {
      apiUrl: ''
    },
    general: {
      appName: 'Default name',
      appShortName: 'default'
    }
  },
  mainSubTitle: 'Default',
  appParts: [new AppPart('core', true)]
};

显示要调试的JSON的模板部分(对于数组示例):

{{ appParts$ | async | json }} {{ loadedAppParts | json }}

使用Observable时: {{ appParts$ | async | json }} {{ loadedAppParts | async | json }}

返回:[ { "name": "core", "loaded": true } ] null

1 个答案:

答案 0 :(得分:2)

在JSON输出中,您可以看到它如下所示:

[ { "name": "core", "loaded": true } ] null

所以appParts$实际上是发出对象数组(Observable<AppPart[]>)而不仅仅是对象(Observable<AppPart>)。

然后,当您使用this.appParts$.filter(a => a.loaded)时,您尝试按照.loaded属性过滤项目,而这些属性并不存在于Array对象中,因此它始终为空。< / p>

实际上,您希望过滤该数组中的对象。换句话说,您需要将数组展平为单个项目。这意味着我们要转此:

[ { "name": "core", "loaded": true }, { "name": "core", "loaded": true }, { "name": "core", "loaded": true } ]

进入这个:

{ "name": "core", "loaded": true }
{ "name": "core", "loaded": true }
{ "name": "core", "loaded": true }

mergeAll()运算符可以执行的操作。在这种情况下,使用mergeAll()与使用merge(array => Observable.from(array))相同。

this.appParts$.mergeAll().filter(a => a.loaded);

现在,当您使用.filter(a => a.loaded)对其进行链接时,您将过滤AppPart个对象。

请注意,使用async过滤器时,它会订阅Observable,并始终只显示从源发出的最后一项

您可以使用toArray()再次将过滤后的项目收集到数组中:

this.appParts$.mergeAll().filter(a => a.loaded).toArray();

这有一个重要的后果。 toArray()运算符仅在源Observable完成后才会发出(但在您的用例中这可能不是问题)。

或者,如果您只想收集所有项目,您还可以使用scan()运算符,该运算符会在源的每个发射上发出集合(但此运算符可能会导致多个视图更新)。

this.appParts$.mergeAll().filter(a => a.loaded).scan((acc, item) => {
    acc.push(item);
    return acc;
}, []);