typescript 使用RxJS进行React式编程,并将数据分为

dgenwo3n  于 2023-02-17  发布在  TypeScript
关注(0)|答案(1)|浏览(95)

我正在尝试对UI组件的Angular 15和RxJS可观察对象进行更被动的处理。我只订阅组件模板(html)中的数据。我有一个从外部系统接收数据的服务。我遇到的问题是数据可能会在多天内接收,需要“拆分”以供显示使用。
在显示画面中,有单独的数据组件,显示从服务调用返回的行。服务对外部主机进行HTTP调用。
this.Entries$ = this.Http_.get<Array<IEntry>>('http://host.com/api/entry');
这个数据是一个带有EntryDate和信息结构(UserId、Description、TimeWorked等)的记录数组。外部API将所有记录作为一个平面数据数组发送回来,这个数组不保证排序,它按照数据库顺序返回,这是记录输入的顺序。任何处理都可能需要排序,但我不确定。

[
   { "EnterDate": 20221025, "UserId": "JohnDoe", "TimeWorked": 2.5, ... },
   { "EnterDate": 20221025, "UserId": "JohnDoe", "TimeWorked": 4.5, ... },
   { "EnterDate": 20221025, "UserId": "BSmith", "TimeWorked": 5, ... },
   { "EnterDate": 20221026, "UserId": "JohnDoe", "TimeWorked": 4, ... },
   { "EnterDate": 20221026, "UserId": "BSmith", "TimeWorked": 5, ... },
   { "EnterDate": 20221026, "UserId": "JohnDoe", "TimeWorked": 2, ... },
]

目前,我的HTML模板在Entries$ observable中循环,而它只循环了一天。

<ng-container *ngFor="let OneEntry of (Entries$ | async)">
    <one-entry-component [data]=OneEntry />
</ng-container>

我希望能够按照EntryDate(显然还有user,但现在只使用EntryDate)将记录数组拆分为不同的数据集,类似于groupBy(),但我不知道如何获取内部记录引用,因为我相信它是groupBy()中的一个Map。
随着数据的分割,我将在页面上寻找多个一天组件,然后在其中有一个条目组件。

|---------------------------------------------------------------|
|                                                               |
| |-One Day 1-------------###-|  |-One Day 2-------------###-|  |
| |                           |  |                           |  |
| |   [ One Line           ]  |  |  [ One Line            ]  |  |
| |   [ One Line           ]  |  |  [ One Line            ]  |  |
| |   [ One Line           ]  |  |  [ One Line            ]  |  |
| |   [ One Line           ]  |  |  [ One Line            ]  |  |
| |                           |  |                           |  |
| |---------------------------|  |---------------------------|  |
|                                                               |
| |-One Day 3-------------###-|  |-One Day 4-------------###-|  |
| |                           |  |                           |  |
| |   [ One Line           ]  |  |  [ One Line            ]  |  |
| |   [ One Line           ]  |  |  [ One Line            ]  |  |
| |   [ One Line           ]  |  |  [ One Line            ]  |  |
| |   [ One Line           ]  |  |  [ One Line            ]  |  |
| |                           |  |                           |  |
| |---------------------------|  |---------------------------|  |
|                                                               |
|---------------------------------------------------------------|

如果回复中有4个不同的日期,那么4个框就会在那里。如果有2个不同的日期,那么只显示2个日期,但这可能是5或6个甚至。
我需要一个Observable,它包含拆分的日期(甚至用户),然后能够将其作为数据传递给<one-day-component [data]=OneDateOneUser$ />。我的组件需要这个,以便我可以计算标题的时间条目,我相信这是一个简单的.pipe(map())操作。
在一天组件中,我将简单地循环OneDateOneUser$ observable,以提取要发送到一个条目组件的单个记录,就像我目前所做的那样。
我相信RxJS groupBy是我所需要的。但是,我是RxJS的新手,在示例中使用内部数据数组对我来说并不清楚。
如果数据是单个记录(如示例),而不是数据数组,则使用示例RxJS引用可以正常工作。

import { of, groupBy, mergeMap, reduce, map } from 'rxjs';
 
of(
  { id: 1, name: 'JavaScript' },
  { id: 2, name: 'Parcel' },
  { id: 2, name: 'webpack' },
  { id: 1, name: 'TypeScript' },
  { id: 3, name: 'TSLint' }
).pipe(
  groupBy(p => p.id, { element: p => p.name }),
  mergeMap(group$ => group$.pipe(reduce((acc, cur) => [...acc, cur], [`${ group$.key }`]))),
  map(arr => ({ id: parseInt(arr[0], 10), values: arr.slice(1) }))
)
.subscribe(p => console.log(p));
 
// displays:
// { id: 1, values: [ 'JavaScript', 'TypeScript' ] }
// { id: 2, values: [ 'Parcel', 'webpack' ] }
// { id: 3, values: [ 'TSLint' ] }

但是,简单地将of()中的数据更改为数组(更像是我的数据如何返回),就会发生故障,而且我不确定如何修复它:

import { of, groupBy, mergeMap, reduce, map } from 'rxjs';
 
of(
[
  { id: 1, name: 'JavaScript' },
  { id: 2, name: 'Parcel' },
  { id: 2, name: 'webpack' },
  { id: 1, name: 'TypeScript' },
  { id: 3, name: 'TSLint' }
]
).pipe(
  groupBy(p => p.id, { element: p => p.name }),
  mergeMap(group$ => group$.pipe(reduce((acc, cur) => [...acc, cur], [`${ group$.key }`]))),
  map(arr => ({ id: parseInt(arr[0], 10), values: arr.slice(1) }))
)
.subscribe(p => console.log(p));
ars1skjm

ars1skjm1#

如果您只是将Array<IEntry>转换为Record<number, IEntry>,其中包含类似lodash的group by和map RxJS操作符,会怎么样?
然后,您可以使用模板上的一些flex-wrapflex-row功能获得所需的结果,只需循环记录的条目:
Check this little working CodePen

import {groupBy} from 'lodash'
const fakeData = [
   { "EnterDate": 20221025, "UserId": "JohnDoe", "TimeWorked": 2.5, ... },
   { "EnterDate": 20221025, "UserId": "JohnDoe", "TimeWorked": 4.5, ... },
   { "EnterDate": 20221025, "UserId": "BSmith", "TimeWorked": 5, ... },
   { "EnterDate": 20221026, "UserId": "JohnDoe", "TimeWorked": 4, ... },
   { "EnterDate": 20221026, "UserId": "BSmith", "TimeWorked": 5, ... },
   { "EnterDate": 20221026, "UserId": "JohnDoe", "TimeWorked": 2, ... },
]

// Replace "of" with your API call
entriesByDate$: Observable<Record<number, IEntry>> = of(fakeData).pipe(
    map(allEntries => groupBy(allEntries, 'EnterDate'))
)
<div *ngIf="entriesByDate$ | async as entries" class="flex flex-row flex-wrap">
    <ng-container *ngFor="let [enterDate, entries] of Object.entries(entries)">
        <entry-group-component [title]="enterDate" [data]="entries" />
    </ng-container>
</div>

相关问题