使用Angular和Rxjs对从存储中检索到的数据进行分组



我是Rxjs和Ngrx的新手。我试图用Angular 12使用Ngrx存储facade以分组格式显示数据数组。数据是visit对象的数组(在Ngrx存储中声明)。我可以从存储中检索数据并通过HTML{{visits$ | async | json}}输出它,结果是正确的数组数据。然而,当我尝试处理这些数据时,Rxjs失败并报错Property 'date' does not exist on type 'Visit[]'.

作为编写Rxjs转换的起点,我将数据直接放入组件中。我可以对数据进行分组并很好地显示数据。

带有

的组件
export interface Visit {
route: string;
name: string;
categoryIcon: string;
subCategoryName: string;
date: Date;
}
const VISITS: Visit[] = [
{
route: '/',
name: 'File Exports',
categoryIcon: 'assessment',
subCategoryName: 'Data Processing',
date: new Date(new Date().setDate(new Date().getDate() - 5)),
},
{
route: '/',
name: 'Recent Orders',
categoryIcon: 'emoji_events',
subCategoryName: 'Record Lists',
date: new Date(new Date().setDate(new Date().getDate() - 5)),
},
{
route: '/',
name: 'Frank Fuvik',
categoryIcon: 'person',
subCategoryName: 'Member Lookup',
date: new Date(new Date().setDate(new Date().getDate() - 5)),
},
{
route: '/',
name: 'Amanda Nollen',
categoryIcon: 'person',
subCategoryName: 'Member Lookup',
date: new Date(),
},
];
import {Component} from '@angular/core';
import { combineAll, groupBy, map, mergeMap, tap, toArray, zip } from 'rxjs/operators';
import { VisitsFacade, Visit } from '@fibonacci/controlcenter/feature-visits';
import { of } from 'rxjs';
@Component({
selector: 'cc-recent',
templateUrl: './recent.component.html',
styleUrls: ['./recent.component.scss'],
})
export class RecentComponent {
constructor(private facade: VisitsFacade) {}
visits$ = this.facade.allVisits$
.pipe(
tap(v => console.log('tap', v)),
groupBy((visit) => visit.date.toISOString().split('T')[0]),
mergeMap((group) => zip(of(group.key), group.pipe(toArray()))),
map(([age, value]) => of({key: age, visits: value})),
combineAll(),
map((group) => group.sort((a, b) => b.key.localeCompare(a.key))),
)
.subscribe();
}

结果是:

[
{
"key": "Data Processing",
"visits": [
{
"route": "/",
"name": "File Exports",
"categoryIcon": "assessment",
"subCategoryName": "Data Processing",
"date": "2022-12-20T19:58:56.551Z"
}
]
},
{
"key": "Member Lookup",
"visits": [
{
"route": "/",
"name": "Frank Fuvik",
"categoryIcon": "person",
"subCategoryName": "Member Lookup",
"date": "2022-12-20T19:58:56.551Z"
},
{
"route": "/",
"name": "Amanda Nollen",
"categoryIcon": "person",
"subCategoryName": "Member Lookup",
"date": "2022-12-25T19:58:56.551Z"
}
]
},
{
"key": "Record Lists",
"visits": [
{
"route": "/",
"name": "Recent Orders",
"categoryIcon": "emoji_events",
"subCategoryName": "Record Lists",
"date": "2022-12-20T19:58:56.551Z"
}
]
}
]

当我将该组件转换为从商店的外观检索数据时,它会错误地输出Property 'date' does not exist on type 'Visit[]'.当我注释掉除了tap(...)之外的所有内容时,该数组显示在浏览器的控制台上。

查看错误消息,它似乎认为类型是一个访问数组而不是单个访问?

我尝试了各种操作符,试图将可观察对象的数据流转换为数组,但没有任何运气。

也许错误是在商店的效果,我已经硬编码的数据现在:

default_visitors与上面的数组完全相同。

import {DEFAULT_VISITS} from './visits.types';
import {Injectable} from '@angular/core';
import {createEffect, Actions, ofType} from '@ngrx/effects';
import {fetch} from '@nrwl/angular';
import * as VisitsActions from './visits.actions';
import * as VisitsFeature from './visits.reducer';
@Injectable()
export class VisitsEffects {
init$ = createEffect(() =>
this.actions$.pipe(
ofType(VisitsActions.init),
fetch({
run: (action) => {
// Your custom service 'load' logic goes here. For now just return a success action...
return VisitsActions.loadVisitsSuccess({visits: DEFAULT_VISITS});
},
onError: (action, error) => {
console.error('Error', error);
return VisitsActions.loadVisitsFailure({error});
},
}),
),
);
constructor(private readonly actions$: Actions) {}
}

希望有人能解释如何存储数据,可观察数据流和rxjs将很好地发挥在一起。

@ 0。MeeKoh证实了我的怀疑,即从商店返回的数据流将自己包裹在访问数组中。下面是一种从数据流中解包数组的方法,但如果有一个更优雅的解决方案,我不会感到惊讶。

visits$ = from(this.facade.allVisits$)
.pipe(
mergeMap((list) => from(list).pipe(
groupBy((visit) => visit.date.toISOString().split('T')[0]),
mergeMap((group) => zip(of(group.key), group.pipe(toArray()))),
map(([age, value]) => of({key: age, visits: value})),
combineAll(),
map((group) => group.sort((a, b) => b.key.localeCompare(a.key))),
)),
)

阅读你的错误信息Property 'date' does not exist on type 'Visit[]'.,这仅仅意味着在你的应用程序中,你有一个访问数组,但你把它当作一个单一的访问对象,然后尝试访问它的日期属性。您可能必须先遍历数组,然后访问日期属性。

最新更新