我的后端经常将数据作为数组返回到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列表的后端返回,我需要从后端请求所有这些项目。
答案 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>