Rxjs的flatMap使用

本文详细解析了Rxjs中的flatMap操作符的使用方法及原理,包括flatMap的参数配置、回调函数的执行流程以及不同场景下的表现。通过具体示例帮助理解flatMap的工作机制。

Rxjs的flatMap使用

flatMap是Rxjs比较绕的一个概念,这里我们只是讲解如何使用。在Rxjs 4.0版本时叫flatMap,在Rxjs 5.0时被更名为margeMap,现在flatMap作为margeMap的别名使用,这是考虑向下兼容。

官方flatMap的定义:
Projects each source value to an Observable which is merged in the output Observable.

mergeMap(project: function(value: T, ?index: number): ObservableInput, resultSelector: function(outerValue: T, innerValue: I, outerIndex: number, innerIndex: number): any, concurrent: number): Observable
名称类型属性描述
projectfunction(value: T, ?index: number): ObservableInput函数,当应用于源 Observable 发出的项时,返回一个 Observable 。
resultSelectorfunction(outerValue: T, innerValue: I, outerIndex: number, innerIndex: number): any可选的函数,它用于产生基于值的输出 Observable 和源(外部)发送和内部 Observable 发送的索引。传递给这个函数参数有:
outerValue: 来自源的值
innerValue:来自投射的Observable 的值
outerIndex: 来自源的值的 “index”
innerIndex: 来自投射的 Observable 的值的 “index”
concurrentnumber可选的,默认值: Number.POSITIVE_INFINITY可以同时订阅的输入 Observables 的最大数量。

返回:
Observable
该 Observable 发出由源 Observable 发出的每项应用投射函数 (和可选的 resultSelector)后的结果,并合并从该转化获得的 Observables 的结果。

Demo

var source = Rx.Observable.of(1,2,3)
  .flatMap(function (x, i) {
                       console.log(`x:${x},i:${i}`);
                       return [x, i];},
           function (x, y, ix, iy) { 
                       console.log(`x:${x},y:${y},ix:${ix},iy:${iy}`);
                       return x + y + ix + iy;});
var subscription = source.subscribe(
                          function (x) { console.log(x);});

JSBin运行

"x:1,i:0"
"x:1,y:1,ix:0,iy:0"
2
"x:1,y:0,ix:0,iy:1"
2
"x:2,i:1"
"x:2,y:2,ix:1,iy:0"
5
"x:2,y:1,ix:1,iy:1"
5
"x:3,i:2"
"x:3,y:3,ix:2,iy:0"
8
"x:3,y:2,ix:2,iy:1"
8

分享一下流程:
- flatMap将1,2,3数据流一次传入flatMap的第一个回调函数,然后输出”x:1,i:0”
- 然后返回[1,0]数组给第二个回调函数,这里的1是value,0是index,是数据的索引号
- 输出”x:1,y:1,ix:0,iy:0”,然后返回2,这里的x参数是outerValue,y是innerValue,ix,是outerIndex,iy是innerIndex
- 在订阅的回调函数中输出2
- 其中的innerValue回退到上一次的值,对应的索引增加,此时值为”x:1,y:0,ix:0,iy:1”,然后返回2
- 在订阅的回调函数中输出2
- 接下来flatMap接受值2,然后传入第一个回调函数project,”x:2,i:1”,返回[2,1]
- 将[2,1]传入第二个回调函数resultSelector,输出”x:2,y:2,ix:1,iy:0”,返回5
- 在订阅的回调函数中输出5
- 然后resultSelector回调函数又一次被调用,传入的参数(2,1,1,1),输出”x:2,y:1,ix:1,iy:1”,并返回5
- 在订阅的回调函数中输出5

下面依次类推,注意的一点是,resultSelector函数会被调用两次,第一次innerValue为当前投射的值,第二次innerValue为上一次的值。

为了验证我们的想法将flatMap的project函数返回值为[x]

var source = Rx.Observable.of(1,2,3)
  .flatMap(function (x, i) {
                       console.log(`x:${x},i:${i}`);
                       return [x];},
           function (x, y, ix, iy) { 
                       console.log(`x:${x},y:${y},ix:${ix},iy:${iy}`);
                       return x + y + ix + iy;});
var subscription = source.subscribe(
                          function (x) { console.log(x);});

输出结果:

"x:1,i:0"
"x:1,y:1,ix:0,iy:0"
2
"x:2,i:1"
"x:2,y:2,ix:1,iy:0"
5
"x:3,i:2"
"x:3,y:3,ix:2,iy:0"
8

根据结果我们能够发现resultSelector函数的执行次数取决于project的返回值。那么我们继续修改返回值为[x,1]

var source = Rx.Observable.of(1,2,3)
  .flatMap(function (x, i) {
                       console.log(`x:${x},i:${i}`);
                       return [x,1];},
           function (x, y, ix, iy) { 
                       console.log(`x:${x},y:${y},ix:${ix},iy:${iy}`);
                       return x + y + ix + iy;});
var subscription = source.subscribe(
                          function (x) { console.log(x);});

输出结果:

"x:1,i:0"
"x:1,y:1,ix:0,iy:0"
2
"x:1,y:1,ix:0,iy:1"
3
"x:2,i:1"
"x:2,y:2,ix:1,iy:0"
5
"x:2,y:1,ix:1,iy:1"
5
"x:3,i:2"
"x:3,y:3,ix:2,iy:0"
8
"x:3,y:1,ix:2,iy:1"
7

结论:

根据这个结果我们能够总结resultSelector函数的y值取决于[x,i]中的i,如果i为0,那么y的值第一次等于x,然后不发生变化。如果i为1那么y第一次等于x,然后需要回退到当前i的值。如果i为2,那么y会从当前的x变化到i,这期间iy的值会从0变化为1。


千万不要高兴的太早,刚刚的结论我们只是尝试着去总结,但是不幸的是错的,没错,比如我们做如下修改

var source = Rx.Observable.of(1,2,3)
  .flatMap(function (x, i) {
                       console.log(`x:${x},i:${i}`);
                       return [2, i];}, // 修改这里
           function (x, y, ix, iy) { 
                       console.log(`x:${x},y:${y},ix:${ix},iy:${iy}`);
                       return x + y + ix + iy;});
var subscription = source.subscribe(
                          function (x) { console.log(x);});

返回结果

"x:1,i:0"
"x:1,y:2,ix:0,iy:0"
3
"x:1,y:0,ix:0,iy:1"
2
"x:2,i:1"
"x:2,y:2,ix:1,iy:0"
5
"x:2,y:1,ix:1,iy:1"
5
"x:3,i:2"
"x:3,y:2,ix:2,iy:0"
7
"x:3,y:2,ix:2,iy:1"
8

这个结果说明什么呢,project返回的数组决定resultSelector回调函数中的y,而resultSelector回调函数中的x是不受影响的,取决于外界传入的值。当project返回的数组中[2,i],决定y的触发次数,如果有两个数组元素就被触发2次,有5个数组元素那么就被触发5次。

最终结论:
resultSelector
project回调函数的返回值决定resultSelector回调函数的参数y即innerValue,同时也决定resultSelector回调函数被触发几次。

如果将flatMap的第二个回调函数去除

var source = Rx.Observable.of(1,2,3)
  .flatMap(function (x, i) {
                       console.log(`x:${x},i:${i}`);
                       return [x, i];});
var subscription = source.subscribe(
                          function (x) { console.log(x);});

JSBin结果

"x:1,i:0"
1
0
"x:2,i:1"
2
1
"x:3,i:2"
3
2

我们可以看到这是正常的结果,flatMap返回Observable的[x,i]数组。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FlyWine

你的鼓励将是我创作的做大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值