web-dev-qa-db-ja.com

RxJS Observable内の配列を「フラット化」する最良の方法

私のバックエンドは頻繁にデータを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。各アイテムを2番目のオブザーバブルに投影する機能が必要なため、RxJSオペレーター(配列メソッド)でアイテムを変換する必要があります。典型的な使用例:バックエンドはアイテムIDのリストを返します。これらのすべてのアイテムをバックエンドからリクエストする必要があります。

30
AngularChef

パラメーターなしでconcatAll()またはmergeAll()を使用できます。

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

これは(mergeMapを含む)RxJS 5でのみ機能します。これは、Observable、配列、配列のようなオブジェクト、Promiseなどを同じ方法で処理するためです。

最終的には次のこともできます:

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

2019年1月:RxJS 6用に更新

27
martin

実際、ストリーム内で必要な場合は、これを使用してください:

.flatMap(items => of(...items))
4
Nick Waits

角度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))
  );
2
englishPete

同期操作の場合は、javascriptの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();
2
olsn