简体   繁体   English

Angular 2 RxJS过滤器可观察到新

[英]Angular 2 RxJS filter to new observable

I'm pretty new to RxJS (using 5.1.1) and trying to understand it in my Angular 2 applciation using angular-redux/store. 我是RxJS的新手(使用5.1.1),并尝试使用angular-redux / store在Angular 2应用程序中了解它。

I've got a store set up and working to get different parts of my state in my application. 我已经建立了一个商店,并致力于在应用程序中获取状态的不同部分。

Now, I'm trying to get AppParts that have the loaded property set to true: 现在,我尝试获取已将load属性设置为true的AppPart:

my state: 我的状态:

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

the select: 选择:

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

now, I'm trying to get a filtered array from this observable: 现在,我试图从这个可观察的对象中获取一个过滤后的数组:

loadedAppParts = [];

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

However, this returns an empty array. 但是,这将返回一个空数组。 I'd like to be able to use the async pipe to get the 'loadedAppParts' if possible too, so I've also tried doing the following: 如果可能的话,我也希望能够使用异步管道来获取“ loadedAppParts”,因此我也尝试了以下操作:

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

So, how can I get a filtered array or observable from my Observable state? 那么,如何从Observable状态获得过滤后的数组或可观察值呢?

Forgot to add my Rootstate: 忘记添加我的Rootstate:

export interface IRootState { };

and my initial state: 和我的初始状态:

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

And the template part that displays the JSON to debug (for the array example): 以及显示要调试的JSON的模板部分(对于数组示例):

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

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

This returns: [ { "name": "core", "loaded": true } ] null 这将返回: [ { "name": "core", "loaded": true } ] null

In the JSON output you can see it looks as follows: 在JSON输出中,您可以看到它如下所示:

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

So the appParts$ is in fact emitting arrays of objects ( Observable<AppPart[]> ) instead of just objects ( Observable<AppPart> ). 因此, appParts$实际上是发出对象数组( Observable<AppPart[]> ),而不仅仅是发出对象数组( Observable<AppPart> )。

Then when you use this.appParts$.filter(a => a.loaded) you're trying to filter the items by .loaded property that doesn't exist on an Array object so it's always empty. 然后,当您使用this.appParts$.filter(a => a.loaded)您尝试通过.loaded属性筛选项目, .loaded属性在Array对象上不存在,因此始终为空。

In fact you want to filter the objects inside that array. 实际上,您想过滤该数组中的对象。 In other words you need to flatten the array into single items. 换句话说,您需要将数组展平为单个项目。 This means we want to turn this: 这意味着我们要改变这个:

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

into this: 到这个:

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

That's what the mergeAll() operator can do. 这就是mergeAll()运算符可以执行的操作。 Using mergeAll() is in this case the same as using merge(array => Observable.from(array)) . 在这种情况下,使用mergeAll()与使用merge(array => Observable.from(array))

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

Now when you chain it with .filter(a => a.loaded) you're filtering the AppPart objects. 现在,当您将其与.filter(a => a.loaded)您正在过滤AppPart对象。

Note that when using async filter it subscribes to the Observable and renders always only the last item emitted from the source. 请注意,使用async过滤器时,它会订阅Observable并始终渲染从源发出的最后一项

You can use toArray() to again collect the filtered items into an array: 您可以使用toArray()再次将过滤后的项目收集到数组中:

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

This has one important consequence. 这有一个重要的后果。 The toArray() operator emits only after the source Observable has completed (but maybe this isn't an issue in your use-case). toArray()运算符仅在源Observable完成后才发出(但在您的用例中这可能不是问题)。

Alternatively if you want to just collect all items you could use also scan() operator that emits the collection on every emission from the source (however this operator might cause multiple view updates). 或者,如果您只想收集所有项目,则还可以使用scan()运算符,它对源中的每个发射都发射集合(但是此运算符可能会导致多个视图更新)。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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