繁体   English   中英

RXjs - flatMap 然后再次“合并”它

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM