Rxjs的flatMap使用
Rxjs的flatMap使用
flatMap是Rxjs比較繞的一個(gè)概念,這里我們只是講解如何使用。在Rxjs 4.0版本時(shí)叫flatMap,在Rxjs 5.0時(shí)被更名為margeMap,現(xiàn)在flatMap作為margeMap的別名使用,這是考慮向下兼容。
官方flatMap的定義:
Projects each source value to an Observable which is merged in the output Observable.
| project | function(value: T, ?index: number): ObservableInput | 函數(shù),當(dāng)應(yīng)用于源 Observable 發(fā)出的項(xiàng)時(shí),返回一個(gè) Observable 。 | |
| resultSelector | function(outerValue: T, innerValue: I, outerIndex: number, innerIndex: number): any | 可選的 | 函數(shù),它用于產(chǎn)生基于值的輸出 Observable 和源(外部)發(fā)送和內(nèi)部 Observable 發(fā)送的索引。傳遞給這個(gè)函數(shù)參數(shù)有: outerValue: 來自源的值 innerValue:來自投射的Observable 的值 outerIndex: 來自源的值的 “index” innerIndex: 來自投射的 Observable 的值的 “index” |
| concurrent | number | 可選的,默認(rèn)值: Number.POSITIVE_INFINITY | 可以同時(shí)訂閱的輸入 Observables 的最大數(shù)量。 |
返回:
Observable
該 Observable 發(fā)出由源 Observable 發(fā)出的每項(xiàng)應(yīng)用投射函數(shù) (和可選的 resultSelector)后的結(jié)果,并合并從該轉(zhuǎn)化獲得的 Observables 的結(jié)果。
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運(yùn)行:
"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數(shù)據(jù)流一次傳入flatMap的第一個(gè)回調(diào)函數(shù),然后輸出”x:1,i:0”
- 然后返回[1,0]數(shù)組給第二個(gè)回調(diào)函數(shù),這里的1是value,0是index,是數(shù)據(jù)的索引號(hào)
- 輸出”x:1,y:1,ix:0,iy:0”,然后返回2,這里的x參數(shù)是outerValue,y是innerValue,ix,是outerIndex,iy是innerIndex
- 在訂閱的回調(diào)函數(shù)中輸出2
- 其中的innerValue回退到上一次的值,對(duì)應(yīng)的索引增加,此時(shí)值為”x:1,y:0,ix:0,iy:1”,然后返回2
- 在訂閱的回調(diào)函數(shù)中輸出2
- 接下來flatMap接受值2,然后傳入第一個(gè)回調(diào)函數(shù)project,”x:2,i:1”,返回[2,1]
- 將[2,1]傳入第二個(gè)回調(diào)函數(shù)resultSelector,輸出”x:2,y:2,ix:1,iy:0”,返回5
- 在訂閱的回調(diào)函數(shù)中輸出5
- 然后resultSelector回調(diào)函數(shù)又一次被調(diào)用,傳入的參數(shù)(2,1,1,1),輸出”x:2,y:1,ix:1,iy:1”,并返回5
- 在訂閱的回調(diào)函數(shù)中輸出5
下面依次類推,注意的一點(diǎn)是,resultSelector函數(shù)會(huì)被調(diào)用兩次,第一次innerValue為當(dāng)前投射的值,第二次innerValue為上一次的值。
為了驗(yàn)證我們的想法將flatMap的project函數(shù)返回值為[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);});輸出結(jié)果:
"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根據(jù)結(jié)果我們能夠發(fā)現(xiàn)resultSelector函數(shù)的執(zhí)行次數(shù)取決于project的返回值。那么我們繼續(xù)修改返回值為[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);});輸出結(jié)果:
"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結(jié)論:
根據(jù)這個(gè)結(jié)果我們能夠總結(jié)resultSelector函數(shù)的y值取決于[x,i]中的i,如果i為0,那么y的值第一次等于x,然后不發(fā)生變化。如果i為1那么y第一次等于x,然后需要回退到當(dāng)前i的值。如果i為2,那么y會(huì)從當(dāng)前的x變化到i,這期間iy的值會(huì)從0變化為1。
千萬不要高興的太早,剛剛的結(jié)論我們只是嘗試著去總結(jié),但是不幸的是錯(cuò)的,沒錯(cuò),比如我們做如下修改
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);});返回結(jié)果
"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這個(gè)結(jié)果說明什么呢,project返回的數(shù)組決定resultSelector回調(diào)函數(shù)中的y,而resultSelector回調(diào)函數(shù)中的x是不受影響的,取決于外界傳入的值。當(dāng)project返回的數(shù)組中[2,i],決定y的觸發(fā)次數(shù),如果有兩個(gè)數(shù)組元素就被觸發(fā)2次,有5個(gè)數(shù)組元素那么就被觸發(fā)5次。
最終結(jié)論:
resultSelector
project回調(diào)函數(shù)的返回值決定resultSelector回調(diào)函數(shù)的參數(shù)y即innerValue,同時(shí)也決定resultSelector回調(diào)函數(shù)被觸發(fā)幾次。
如果將flatMap的第二個(gè)回調(diào)函數(shù)去除
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結(jié)果
"x:1,i:0" 1 0 "x:2,i:1" 2 1 "x:3,i:2" 3 2我們可以看到這是正常的結(jié)果,flatMap返回Observable的[x,i]數(shù)組。
總結(jié)
以上是生活随笔為你收集整理的Rxjs的flatMap使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Problem D: 顺序串的基本运算
- 下一篇: Being a Good Boy in