在非完整的RxJS流中展平嵌套数据结构

时间:2017-01-31 14:33:31

标签: angular ecmascript-6 rxjs rxjs5 ngrx

我希望压缩我从商店获得的值,并在商店发布时将它们作为单个数组发出。

在下面的 No-RxJS 示例的同步版本中很容易,但我无法弄清楚如何使用RxJS。

我假设我可以使用RxJS缓冲来自单个.next调用的值。

我应该使用RxJS运算符吗?如果是,那么如何使嵌套数据结构变平?

这是我想要实现的最小例子。

const store$ = new Rx.BehaviorSubject([])

store$.next([
  {
    id: 1,
    items: [
      {
        id: 1,
        title: 'Foo'
      },
      {
        id: 2,
        title: 'Bar'
      }
    ]
  },
  {
    id: 2,
    items: [
      {
        id: 3,
        title: 'Fizz'
      },
      {
        id: 4,
        title: 'Buzz'
      }
    ]
  },
]);

// Desired output: [ "Foo", "Bar", "Fizz", "Buzz" ]

store$
  .filter(({length}) => length > 0)
  .flatMap(group => group)
  .flatMap(({items}) => items)
  .map(({title}) => title)
  .subscribe(console.log) // Emits separate values :-(

// No-RxJs approach

store$
  .filter(({length}) => length > 0)
  .map(groups => groups
        .map(
          ({ items }) => items.map(
            ({ title }) => title
          )
        )
        .reduce((next, acc) => [ ...acc, ...next ], []))
  .subscribe(console.log) // Works as expected.
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.0.1/Rx.js"></script>

1 个答案:

答案 0 :(得分:1)

正如@zeroflagl在评论中所建议的,toArray方法就像魅力一样。

由于它仅适用于已完成的observable,因此我必须swithchMap使用一个Observable,它使用take(1)来获取具有当前商店值的已完成的observable。

store$
    .filter(({ length }) => length > 0)
    .switchMap(() => store$.take(1)
        .flatMap(group => group)
        .flatMap(({ items }) => items)
        .map(({ title }) => title)
        .toArray()
    )
    .subscribe(console.log) // Emits flat array