Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 267
AngularChef Avatar asked Oct 03 '22 09:10

AngularChef


People also ask

What is flattening operator in RxJS?

Flattening operators come to our rescue when we have a nested subscription i.e subscribing to an observable within another subscription. This can be pretty annoying to track and debug. Its similar to “Callback hell” scenario where we have nested callbacks.

What is flattening an observable?

Flattening just means — “ subscribing inside a subscribe ” The only way to extract values out of the returned observable will be to subscribe to it.

Why we use pipe in observable?

The pipe method of the Angular Observable is used to chain multiple operators together. We can use the pipe as a standalone method, which helps us to reuse it at multiple places or as an instance method. In this tutorial, we will take a look at the pipe and learn how to use it in an Angular Application.


1 Answers

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

like image 64
martin Avatar answered Oct 22 '22 06:10

martin