我希望压缩我从商店获得的值,并在商店发布时将它们作为单个数组发出。
在下面的 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>
答案 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