[英]RXjs - flatMap then “merge” it again
我正在学习 RXjs,我想了解事情是如何运作的。 所以这就是为什么我设想了一个场景,我创建Observable.of
并传入一个数组。 我知道, Observable.from
会更合适,但我正在学习事情是如何运作的。
所以,这是我的代码:
let sourceZero = Rx.Observable
.of([{name: 'James', age: 25}, {name: 'Angelina', age: 30}]);
sourceZero.subscribe(
x => console.log(x)
);
这按预期工作:订阅的值是数组。
好的,现在我想过滤该数组。 虽然我知道我可以做很多其他的选择,例如在代码的订阅部分,我想在创建 observable 时过滤它。 所以,我使用了flatMap
,就像这样。
let source = Rx.Observable
.of([{name: 'James', age: 25}, {name: 'Angelina', age: 30}])
.flatMap(x => x)
.filter(x => x.age > 15)
虽然这符合我的要求,但结果不再是数组,而是对象流。
现在,我的问题是,如何再次从这些过滤后的数据中创建一个数组? 我不想将单个对象传递给订阅部分,而是传递一个数组,就像第一个示例中的情况一样。
所以,目前的结果是:
[object Object] {
age: 25,
name: "James"
}
[object Object] {
age: 30,
name: "Angelina"
}
但我希望它是:
[[object Object] {
age: 25,
name: "James"
}, [object Object] {
age: 30,
name: "Angelina"
}]
基本上,我正在寻找一种方法来反转flatMap
。 我使用.concatMap(x => Rx.Observable.of(x))
无济于事。
代码可在此处获得: http : //jsbin.com/lujeqowofi/1/edit
Reduce
运算符是您正在寻找的:
let source = Rx.Observable
.of([{name: 'James', age: 25}, {name: 'Angelina', age: 30}])
.flatMap(x => x)
.reduce((acc, x) => (acc instanceof Array) ? acc.push(x): [acc, x]);
我认为您误解了 RxJS 的含义。 也许如果我带你了解你的代码在做什么,你就会明白你是怎么出错的。
let source = Rx.Observable
.of([{name: 'James', age: 25}, {name: 'Angelina', age: 30}]) // 1.
.flatMap(x => x) // 2.
.filter(x => x.age > 15) // 3.
Observable 的关键抽象是它是“随时间变化的值流”。 我们的意思是 observable 发出单个值,一次一个值。 发出的那些值可能是复杂的对象甚至是数组,但它们仍然是单个值。
在您的代码中,当您说 Observable.of()(第 1 步)时,您创建了一个只能发出一个值的 observable:您的数组。
然后,当你平面映射(第 2 步)时,你做了一些我认为你不应该做的事情。 flatMap 操作符旨在与发出 Observables 作为其值的 Observable 一起使用。 但是,在您的第 2 步中,您的原始 observable 不是发出 observable,而是发出一个数组。 但是, flatMap 能够将数组转换为可观察的,所以它就是这样做的。
但是此时,您现在有一个 observable 将发出 2 个值:第一个 -> {name: 'James', age:25 }
然后 --> {name: 'Angelina', age: 30}
。 此时,您的 observable 不再处理数组。 它正在处理单个对象。
如果您的目标只是过滤原始数组以仅包含年龄 > 15 的项目,则在数组上使用地图。
要补充@Serginho 的答案,使用空数组作为seed
(第一个值)可能会更清晰
const toArray = reduce((acc, x) => {
acc.push(x);
return acc;
}, Array<any>());
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.