为什么我们需要使用flatMap?

时间:2015-11-02 05:54:06

标签: javascript rxjs

我开始使用RxJS,我不明白为什么在这个例子中我们需要使用像O(n)flatMap这样的函数;这里的数组数组在哪里?

concatAll

如果有人可以直观地解释发生的事情,那将非常有帮助。

11 个答案:

答案 0 :(得分:100)

['a','b','c'].flatMap(function(e) {
    return [e, e+ 'x', e+ 'y',  e+ 'z'  ];
});
//['a', 'ax', 'ay', 'az', 'b', 'bx', 'by', 'bz', 'c', 'cx', 'cy', 'cz']


['a','b','c'].map(function(e) {
    return [e, e+ 'x', e+ 'y',  e+ 'z'  ];
});
//[Array[4], Array[4], Array[4]]

当你有一个Observable时,你会使用flatMap,它的结果是更多Observables。

如果你有一个由另一个observable生成的observable,你不能直接过滤,缩小或映射它,因为你有一个Observable而不是数据。如果你生成一个observable,请在地图上选择flatMap;那你没事。

与第二个片段一样,如果您正在进行异步操作,则需要使用flatMap。



var source = Rx.Observable.interval(100).take(10).map(function(num){
    return num+1
});
source.subscribe(function(e){
    console.log(e)
})

<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.4.1/Rx.min.js"></script>
&#13;
&#13;
&#13;

&#13;
&#13;
var source = Rx.Observable.interval(100).take(10).flatMap(function(num){
    return Rx.Observable.timer(100).map(() => num)
});
source.subscribe(function(e){
    console.log(e)
})
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.4.1/Rx.min.js"></script>
&#13;
&#13;
&#13;

答案 1 :(得分:62)

当我开始看Rxjs时,我偶然发现了那块石头。帮助我的是以下几点:

  • 来自reactivex.io的文档。例如,flatMaphttp://reactivex.io/documentation/operators/flatmap.html
  • 来自rxmarbles的文档:http://rxmarbles.com/。你在那里找不到flatMap,你必须改为mergeMap(另一个名字)。
  • 您失踪的Rx简介:https://gist.github.com/staltz/868e7e9bc2a7b8c1f754。它解决了一个非常相似的例子。特别是它解决了一个事实,即承诺类似于只发出一个值的可观察值。
  • 最后查看来自RxJava的类型信息。没有输入的Javascript在这里没有帮助。基本上,如果Observable<T>表示推送类型为T的值的可观察对象,则flatMapT' -> Observable<T>类型的函数作为其参数,并返回Observable<T>map采用T' -> T类型的函数并返回Observable<T>

    回到你的例子,你有一个函数,它从url字符串产生promises。所以T' : stringT : promise。根据我们之前所说的promise : Observable<T''>T : Observable<T''>T'' : html。如果你在map中放置了这个promise生成函数,那么当你想要的是Observable<Observable<T''>>时,你得到Observable<T''>:你希望observable发出html值。 flatMap被调用,因为它会使map的结果变平(删除可观察的图层)。根据你的背景,这对你来说可能是中国人,但是从我这里输入信息和图纸后,一切都变得清晰:http://reactivex.io/documentation/operators/flatmap.html

答案 2 :(得分:21)

get("posts")将Observable发出的项目转换为新的Observable,然后将这些项目的排放量变为单个Observable。

查看下面的场景,其中flatMap返回的是一个Observable&#34; flattened&#34; myObservable.map(e => get("posts")).subscribe(o => console.log(o)); // this would log Observable objects to console. myObservable.flatMap(e => get("posts")).subscribe(o => console.log(o)); // this would log posts to console.

select reference_number, event_type, created_timestamp
from table_name best
left join table_name better_than on better_than.reference_number = best.reference_number and better_than.created_timestamp > best.created_timestamp
where better_than is null;

答案 3 :(得分:16)

它不是一个数组数组。这是可观察到的观察结果。

以下命令返回一个可观察的字符串流。

requestStream
  .map(function(requestUrl) {
    return requestUrl;
  });

虽然这会返回一个可观察的json流可观察流

requestStream
  .map(function(requestUrl) {
    return Rx.Observable.fromPromise(jQuery.getJSON(requestUrl));
  });

flatMap自动为我们展平observable所以我们可以直接观察json流

答案 4 :(得分:15)

人们倾向于过于复杂化,给出的定义是:

  

flatMap将Observable发出的项转换为   可观测量,然后将那些排放量减少为单一   可观察到的

我发誓这个定义仍然让我感到困惑,但我将以最简单的方式解释它,即使用一个例子

我们的情况:我们有一个observable,它返回我们将用于进行HTTP调用的数据(简单URL),该调用将返回包含我们需要的数据的observable,以便您可以看到这样的情况:

Observable 1
    |_
       Make Http Call Using Observable 1 Data (returns Observable_2)
            |_
               The Data We Need

因为你可以看到我们无法直接获得我们需要的数据所以第一种检索数据的方法我们可以使用这样的普通订阅:

Observable_1.subscribe((URL) => {
         Http.get(URL).subscribe((Data_We_Need) => {
                  console.log(Data_We_Need);
          });
});

这可行,但正如你所看到的,我们必须嵌套订阅以获取我们目前看起来并不坏的数据,但想象一下我们有10个嵌套订阅将无法维护。

因此,更好的方法是使用运算符flatMap来执行相同的操作但是让我们避免嵌套订阅:

Observable_1
    .flatMap(URL => Http.get(URL))
    .subscribe(Data_We_Need => console.log(Data_We_Need));

答案 5 :(得分:13)

Observable是一个发出事件流的对象:Next,Error and Completed。

当你的函数返回一个Observable时,它不会返回一个流,而是一个Observable的实例。 flatMap运算符只是将该实例映射到流。

flatMap相比,这是map的行为:执行给定的函数并将生成的对象展平为流。

答案 6 :(得分:13)

简单:

[1,2,3].map(x => [x, x * 10])
// [[1, 10], [2, 20], [3, 30]]

[1,2,3].flatMap(x => [x, x * 10])
// [1, 10, 2, 20, 3, 30]]

答案 7 :(得分:7)

这里显示使用subscribes的flatMap的等效实现。

没有flatMap:

this.searchField.valueChanges.debounceTime(400)
.subscribe(
  term => this.searchService.search(term)
  .subscribe( results => {
      console.log(results);  
      this.result = results;
    }
  );
);

使用flatMap:

this.searchField.valueChanges.debounceTime(400)
    .flatMap(term => this.searchService.search(term))
    .subscribe(results => {
      console.log(results);
      this.result = results;
    });

http://plnkr.co/edit/BHGmEcdS5eQGX703eRRE?p=preview

希望它可以提供帮助。

奥利弗。

答案 8 :(得分:5)

使用flatMap

var requestStream = Rx.Observable.just('https://api.github.com/users');

var responseMetastream = requestStream
  .flatMap(function(requestUrl) {
    return Rx.Observable.fromPromise(jQuery.getJSON(requestUrl));
  });

responseMetastream.subscribe(json => {console.log(json)})

没有flatMap

var requestStream = Rx.Observable.just('https://api.github.com/users');

var responseMetastream = requestStream
  .map(function(requestUrl) {
    return Rx.Observable.fromPromise(jQuery.getJSON(requestUrl));
  });

responseMetastream.subscribe(jsonStream => {
  jsonStream.subscribe(json => {console.log(json)})
})

答案 9 :(得分:0)

flatMap将Observable发出的项目转换为Observable, 然后将这些元素的排放归为一个可观察的

我并不傻,但必须阅读10遍,但仍然听不懂。当我阅读代码片段时:

[1,2,3].map(x => [x, x * 10])
// [[1, 10], [2, 20], [3, 30]]

[1,2,3].flatMap(x => [x, x * 10])
// [1, 10, 2, 20, 3, 30]

然后我可以理解发生了什么,它有两件事:

flatMap

  1. 地图:将*)发射的项目转换成Observables。
  2. 平面:然后将这些可观察对象合并为一个可观察对象。

*)转换词表示可以将项目转换成其他形式。

然后 merge 运算符变得很清楚,它会在没有映射的情况下进行展平。为什么不叫它 mergeMap ?似乎还有一个别名 mergeMap ,其名称为 flatMap

答案 10 :(得分:0)

<块引用>

flatMap 用于将数组的数组展平为单个数组。

map 只是将一个数组转换为另一个数组。例如,假设您有一个像这样的 person 对象列表:

const friends = [
    {name: 'Dave', kids: ['Max', 'Jack']},
    {name: 'Max', kids: ['Sam', 'Alex', 'Megan']},
    {name: 'Jordan', kids: ['Mason', 'Cameron', 'Kaylin']}
];

但您真正需要的是一组人名(即字符串:[“Dave”、“Max”、“Jordan”])。要将这个 person 对象数组转换为字符串数组,您首先需要像这样定义映射函数:

const mapFunction = p -> p.name;

然后,像这样使用array.map:

const names = friends.map(mapFunction);

返回:

["Dave", "Max", "Jordan"]

flatMap 与 map 类似,都将一个数组转换为另一个数组。但是有一些细微的区别: 首先,map一般是一对一的东西。映射函数接收一个对象并返回一个对象:

p -> p.name

这意味着 3 个 person 对象会产生 3 个名字。

另一方面,

flatMap 是一对多的东西。映射函数接受一个对象,但返回一个数组:

p -> p.kids

最终结果:输入 3 个人物会产生 8 个孩子的名字。因此,这段代码:

const mapFunction = p -> p.kids;
const kidNames = friends.flatMap(mapFunction);

将返回:

["Max", "Jack", "Sam", "Alex", "Megan", "Mason", "Cameron", "Kaylin"]