为什么我们需要使用flatMap?

use*_*232 82 javascript rxjs

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

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(url => {console.log(url)})
Run Code Online (Sandbox Code Playgroud)

如果有人可以直观地解释发生了什么,那将非常有帮助.

ser*_*kan 110

['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]]
Run Code Online (Sandbox Code Playgroud)

当你有一个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)
})
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.4.1/Rx.min.js"></script>
Run Code Online (Sandbox Code Playgroud)

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)
})
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.4.1/Rx.min.js"></script>
Run Code Online (Sandbox Code Playgroud)


use*_*222 67

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

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

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

  • 我忘了提一下,您应该能够将return Rx.Observable.fromPromise(jQuery.getJSON(requestUrl));简化为return jQuery.getJSON(requestUrl);,因为FlatMap还接受选择器函数,该选择器函数返回一个诺言,即类型为“ T”-&gt; Promise的函数。 (2认同)
  • 哇,GitHub Gist(https://gist.github.com/staltz/868e7e9bc2a7b8c1f754)真是太棒了。我推荐给使用任何ReactiveX库(如RxJS)的任何人。 (2认同)

Emm*_*osu 25

flatMap 将Observable发出的项目转换为新的Observable,然后将那些项目的排放量变为单个Observable.

查看下面的场景,其中get("posts")返回一个被"展平"的Observable flatMap.

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.
Run Code Online (Sandbox Code Playgroud)

  • 不错,简单的答案。我认为这可能是最好的。 (2认同)

Ham*_*our 22

人们倾向于通过给出以下定义来使事情变得复杂:

flatMap将Observable发出的项目转换为Observables,然后将这些项目的排放量变为单个Observable

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

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

Observable 1
    |_
       Make Http Call Using Observable 1 Data (returns Observable_2)
            |_
               The Data We Need
Run Code Online (Sandbox Code Playgroud)

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

Observable_1.subscribe((URL) => {
         Http.get(URL).subscribe((Data_We_Need) => {
                  console.log(Data_We_Need);
          });
});
Run Code Online (Sandbox Code Playgroud)

这是有效的,但你可以看到我们必须嵌套订阅以获取我们的数据,这当前看起来并不坏,但想象我们有10个嵌套订阅,这将是不可维护的.

所以一个更好的方法来处理这个只是使用运算符flatMap,它将做同样的事情,但让我们避免嵌套订阅:

Observable_1
    .flatMap(URL => Http.get(URL))
    .subscribe(Data_We_Need => console.log(Data_We_Need));
Run Code Online (Sandbox Code Playgroud)


Luc*_*ius 16

它不是一个数组数组.这是一个可观察到的观察者.

以下内容返回一个可观察的字符串流.

requestStream
  .map(function(requestUrl) {
    return requestUrl;
  });
Run Code Online (Sandbox Code Playgroud)

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

requestStream
  .map(function(requestUrl) {
    return Rx.Observable.fromPromise(jQuery.getJSON(requestUrl));
  });
Run Code Online (Sandbox Code Playgroud)

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

  • 很难理解这个概念,你能不能在视觉上添加注释你的意思是"返回一个可观察的可观察流json流".谢谢. (3认同)

小智 15

简单:

[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]]
Run Code Online (Sandbox Code Playgroud)


Akk*_*nZA 13

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

当函数返回一个Observable时,它不会返回一个流,而是一个Observable实例.该flatMap运营商仅仅是实例映射到一个流.

这与以下行为flatMap相比map:执行给定的函数并将生成的对象展平为流.


小智 9

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

没有flatMap:

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

使用flatMap:

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

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

希望它可以帮助.

奥利维尔.


小智 6

使用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)})
Run Code Online (Sandbox Code Playgroud)

没有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)})
})
Run Code Online (Sandbox Code Playgroud)


Her*_*lom 5

flatMap 将 Observable 发出的项转换为 Observables,然后将这些项的发射扁平化为单个 Observable

我不傻,但我必须读十遍才能明白。

Map 的工作方式类似于数组中每个项目的 for...each 并转换数组中的项目,但保持数组不变:

[1,2,3].map(x => [x, x * 10])
// [[1, 10], [2, 20], [3, 30]]
Run Code Online (Sandbox Code Playgroud)

Flatmap 与 map 的作用相同,但也“展平”数组:

[1,2,3].flatMap(x => [x, x * 10])
// [1, 10, 2, 20, 3, 30]
Run Code Online (Sandbox Code Playgroud)

平面地图

  1. map : 将 *) 发出的项目转换为 Observables。
  2. flat:然后将这些 Observable 合并为一个 Observable。

*) 变换词表示该项目可以变换为其他东西。

然后合并运算符就变得清楚了,它在没有映射的情况下进行扁平化。为什么不将其称为mergeMap?似乎还有一个 Alias mergeMap具有该名称的flatMap