在订阅内部使用RxJS的组

时间:2019-08-17 22:07:40

标签: angular rxjs

我在https://www.learnrxjs.io/operators/transformation/groupby.html

了解了分组依据

但是,当我尝试仅按“类型”列进行分组时,却没有得到所请求的结果。

为了组成“类型”列然后显示在component.html上,我缺少什么部分?

您从订阅中获取类型的数据,然后通过订阅中的代码应用分组。

谢谢!

Stackblitz = https://stackblitz.com/edit/angular-twngjm

1 个答案:

答案 0 :(得分:1)

您的操作方式:

服务:

Dataa() {
  return this._http.get<any[]>('https://api.github.com/users'); // not a promise
}

组件:

_test; // not private

ngOnInit() {
  this._test = this._apiService.Dataa().pipe( // set observable to variable
    switchMap(data => from(data).pipe( // array to stream
      groupBy((item: any) => item.type), // group by type
      mergeMap(group => zip(of(group.key), group.pipe(toArray()))), // convert each group back to array and zip with key
      reduce((acc, val) => acc.concat([val]), []) // collect emissions into array of arrays
    ))
  );
}

模板:

<div style="display: flex;"> <!-- just styles into columns -->
  <div *ngFor="let item of _test | async"> <!-- subscribe with async and iterate grouped arrays -->
    {{item[0]}} <!-- first item is headers, display it -->
    <div *ngFor="let user of item[1]"> <!-- second item is the grouped items, which you iterate -->
      {{user.login}} <!-- show your data here -->
    </div>
  </div>
</div>

闪电战:https://stackblitz.com/edit/angular-cbnkjv?file=src%2Fapp%2Fapp.component.ts

说明:

首先,无需在此处转换为诺言。使用可观察物。模板中访问的变量也不能是私有的。

接下来,您的数据已经是数组,因此您需要使用switchMap-> from将其转换为流,以便groupBy可以对其进行操作,因为groupBy仅适用于流。

groupBy产生一个GroupedObservable,基本上是一堆由groupBy中指定属性分组的项目流。

因此,在那之后,您需要将Map合并到这些流中。然后使用组密钥将其压缩,然后将流转换为数组,就得到了[groupKey,[... group中的项目...]]这样的结构。

最后,mergeMap会逐个发出每个组,因此您可以使用reduce将它们全部收集到一个数组中

然后,您修改模板以使其与带有嵌套ngFors的该arrays数组结构一起使用。我还选择使用异步管道来处理我的订阅。

讨论:

这一切值得吗?除非您真正处理的是数据流(例如来自Web套接字或用户操作流),否则可能不会。无需将数组强制为可观察的组,然后再转换回数组并进行收集。您可以只使用lodash之类的实用程序库,并在其上同步运行地图运算符。如果这样做的话,代码将简化为这样:

ngOnInit() {
  this._test = this._apiService.Dataa().pipe(
    map(data => _.groupBy(data, 'type')),
    map(grouped => Object.entries(grouped)) // _.groupBy gives a keyed object, this just converts to the same array of array structure as rx groupBy
  );
}

真的不想要另一个依赖吗?简单的分组功能:

function groupBy(arr, prop) {
  return arr.reduce((acc, val) => {
    const key = val[prop];
    acc[key] = (acc[key] || []).concat([val]); 
    return acc;
  }, {});
}