最好的方式来平和" RxJS Observable中的数组

时间:2017-02-27 09:59:14

标签: angular rxjs rxjs5

我的后端经常将数据作为数组返回到RxJS 5 Observable中(我使用Angular 2)。

我经常发现自己想要使用RxJS运算符单独处理数组项,并使用以下代码(JSBin)执行此操作:

const dataFromBackend = Rx.Observable.of([
  { name: 'item1', active: true },
  { name: 'item2', active: false },
  { name: 'item3', active: true }
]);

dataFromBackend
  // At this point, the obs emits a SINGLE array of items
  .do(items => console.log(items))
  // I flatten the array so that the obs emits each item INDIVIDUALLY
  .mergeMap(val => val)
  // At this point, the obs emits each item individually
  .do(item => console.log(item))
  // I can keep transforming each item using RxJS operators.
  // Most likely, I will project the item into another obs with mergeMap()
  .map(item => item.name)
  // When I'm done transforming the items, I gather them in a single array again
  .toArray()
  .subscribe();

mergeMap(val => val)行并不是非常惯用的。

是否有更好的方法将变换应用于Observable发出的数组成员?

NB。我希望RxJS运算符(vs数组方法)转换我的项目,因为我需要能够将每个项目投影到第二个observable。典型用例:项目ID列表的后端返回,我需要从后端请求所有这些项目。

5 个答案:

答案 0 :(得分:22)

您可以在没有任何参数的情况下使用concatAll()mergeAll()

dataFromBackend.pipe(
  tap(items => console.log(items)),
  mergeAll(), // or concatAll()
)

这个(包括mergeMap)仅适用于RxJS 5,因为它以相同的方式处理Observable,数组,类数组对象,Promises等。

最后你也可以这样做:

mergeMap(val => from(val).pipe(
  tap(item => console.log(item)),
  map(item => item.name),
)),
toArray(),

2019年1月:更新了RxJS 6

答案 1 :(得分:3)

实际上如果您需要在流中使用它,请使用:

.flatMap(items => of(...items))

答案 2 :(得分:2)

6号角音符。

如果您用作管道运算符,则do称为tap!

https://www.learnrxjs.io/operators/utility/do.html 这是一个例子。

// RxJS 
import { tap, map, of, mergeMap} from 'rxjs/operators';

backendSource
  .pipe(
   tap(items => console.log(items)),
   mergeMap(item => item ),
   map(item => console.log(item.property))
  );

答案 3 :(得分:1)

如果是同步操作,我建议使用javascript' s Array.map,它甚至可以为您节省一些性能:

const dataFromBackend = Rx.Observable.of([
  { name: 'item1', active: true },
  { name: 'item2', active: false },
  { name: 'item3', active: true }
]);

dataFromBackend
  .map(items => items.map(item => item.name))
  .subscribe();

答案 4 :(得分:0)

我有一个类似的问题:

以下

  • 针对每个项目运行
  • 拔出一个深度嵌套的对象
  • 将服务器响应转换回数组
  • 在模板中作为异步管道使用
    this.metaData = backendPostReq(body)
      .pipe(
        mergeMap(item => item),   // splits the array into individual objects
        pluck('metaData', 'dataPie', 'data'), // plucks deeply nested property
        toArray()  // converted back to an array for ag grid
      )

    <ag-grid-angular
        *ngIf="metaData | async as result"
        [gridOptions]="dataCollectionConfig"
        [rowData]="result"
        [modules]="modules"
        class="ag-theme-balham data-collection-grid"
    >
    </ag-grid-angular>