Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
997 views
in Technique[技术] by (71.8m points)

angular - Best way to "flatten" an array inside an RxJS Observable

My backend frequently returns data as an array inside an RxJS 5 Observable (I'm using Angular 2).

I often find myself wanting to process the array items individually with RxJS operators and I do so with the following code (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();

The mergeMap(val => val) line doesn't feel very idiomatic.

Is there a better way to apply transformations to the members of an array that's emitted by an Observable?

NB. I want RxJS operators (vs array methods) to transform my items because I need the ability to project each item into a second observable. Typical use case: backend returns of list of item ids and I need to request all of these items from the backend.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can use concatAll() or mergeAll() without any parameter.

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

This (including mergeMap) works only in RxJS 5 because it treats Observables, arrays, array-like objects, Promises, etc. the same way.

Eventually you could do also:

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

Jan 2019: Updated for RxJS 6


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...