![](/img/trans.png)
[英]Angular 5 RxJs concatMap,switchMap,mergeMap which?
[英]flatMap, mergeMap, switchMap and concatMap in rxjs?
請哪位大神解釋一下Javascript(在angular視角下,rxjs 5)中SwitchMap和FlatMap的區別
在我的理解中。
SwitchMap僅發出最新的可觀察值並取消先前的可觀察值。
flatMap收集所有單獨的 observable 並在一個數組中返回所有 observable,而不關心 observable 的順序。 異步工作。
concatMap保留順序並發出所有可觀察值,同步工作
是對的嗎?
mergeMap與上面的工作方式有何不同?
有人,請舉例說明。
從以前的答案中提取:
這是一個示例,說明當源是直接項 (0,1,2,3,4) 並且 map 函數創建一個將每個項延遲 500 毫秒的 Observable 時,每個運算符的行為方式:
const { mergeMap, flatMap, concatMap, switchMap, exhaustMap } = Rx.operators; const example = operator => () => Rx.Observable.from([0,1,2,3,4]) .pipe( operator(x => Rx.Observable.of(x).delay(500)) ) .subscribe(console.log, () => {}, () => console.log(`${operator.name} completed`)); const mm = example(mergeMap); const fm = example(flatMap); const cm = example(concatMap); const sm = example(switchMap); const em = example(exhaustMap);
.examples > div { cursor: pointer; background-color: #4CAF50; color: white; padding: 7px 16px; display: inline-block; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.8/Rx.js"></script> <div class='examples'> <div onClick='mm()'>mergeMap </div> <div onClick='fm()'>flatMap</div> <div onClick='cm()'>concatMap</div> <div onClick='sm()'>switchMap</div> <div onClick='em()'>exhaustMap</div> </div>
在下面的彈珠圖中,在5ms 、 10ms 、 20ms發射的源流將被*映射到timer(0, 3)
,限制為 3 個發射:
在這里玩這個大理石圖: “mergeMap vsexhaustMap vs switchMap vs concatMap”
已經有了所有這些很棒的答案,我想添加一個更直觀的解釋
希望它可以幫助某人
@ZahiC,很酷的答案 - 我喜歡在代碼示例中使用函數組合。 如果可以的話,我想借用它來使用定時觀察來說明一些額外的要點。
這些操作符都是像map()
這樣的轉換操作符,共同的特點是它們有一個外層和內層的observable。 關鍵的區別在於外部 observable控制內部 observable 的方式。
為了對比它們,我的代碼示例成對運行它們,以[outerValue,innerValue]
的形式輸出值。 我在測試中添加了間隔,並更改了內部延遲,以便在時間上有一些重疊(使用的公式是delay((5-x)*200)
)。
這些都輸出所有值,不同的是排序。
mergeMap - 按內部 observable 排序
[0,0],[1,0],[0,1],[2,0],[1,1],[3,0],[2,1],[4,0],[3 ,1],[4,1]concatMap - 按外部 observable 排序
[0,0],[0,1],[1,0],[1,1],[2,0],[2,1],[3,0],[3,1],[4 ,0],[4,1]
從輸出來看,mergeMap 外發射可以在序列中延遲,但 concatMap 遵循嚴格的外發射序列。
這些都限制了輸出。
switchMap - 最后節流
[3,0],[4,0],[4,1]排氣地圖 - 首先節流
[0,0],[0,1],[4,0],[4,1]
從輸出中,switchMap 會限制任何不完整的內部發射,但exhaustMap 會限制后續的發射,直到較早的發射完成。
我之所以這樣做是因為 switchmap 經常用在真正應該使用 mergeMap 的 SO 答案中。
mergeMap - 按內部 observable 排序
[0,0],[1,0],[0,1],[2,0],[1,1],[3,0],[2,1],[4,0],[3 ,1],[4,1]switchMap - 最后節流
[3,0],[4,0],[4,1]
主要的收獲是 switchMap 輸出是不可預測的,具體取決於內部可觀察的時間,例如,如果內部是http,則結果可能取決於連接速度。
console.clear() const { mergeMap, flatMap, concatMap, switchMap, exhaustMap, delay, map, take, toArray } = Rx.operators; const note = { mergeMap: 'Order by inner observable', concatMap: 'Order by outer observable', switchMap: 'Throttle by last', exhaustMap: 'Throttle by first', } const title = (operator) => { const opName = operator.name.replace('$1','') return `${opName} - ${note[opName]}` } const display = (x) => { return map(y => `[${x},${y}]`) } const inner = (x) => Rx.Observable.timer(0,500) .pipe( delay((5-x)*200), display(x), take(2) ) const example = operator => () => { Rx.Observable.interval(500).take(5) .pipe( operator(x => inner(x)), toArray(), map(vals => vals.join(',')) ) .subscribe(x => { console.log(title(operator)) console.log(x) }); }; const run = (fn1, fn2) => { console.clear() fn1() fn2() } const mmVcm = () => run(example(mergeMap), example(concatMap)); const smVem = () => run(example(switchMap), example(exhaustMap)); const mmVsm = () => run(example(mergeMap), example(switchMap));
.examples > div { cursor: pointer; background-color: #4CAF50; color: white; padding: 7px 16px; display: inline-block; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.8/Rx.js"></script> <div class='examples'> <div onClick='mmVcm()'>mergeMap vs concatMap </div> <div onClick='smVem()'>switchMap vs exhaustMap</div> <div onClick='mmVsm()'>mergeMap vs switchMap </div> </div>
這在開始時有點長,至少對我來說是這樣。
無論如何,考慮一下:
flatMap
是mergeMap
mergeMap
名稱 - mergeMap
方法接受一個可選參數concurrency
,它定義了可以同時訂閱多少個 Observables
concatMap
等於並發設置為 1 的mergeMap
使用mergeMap
您不會丟失您在回答中建議的合並的 Observables 發出的任何事件
switchMap
像您描述的switchMap
工作(有關更多詳細信息,請參閱這篇不錯的文章https://blog.angular-university.io/rxjs-switchmap-operator/ )
不久前,我制作了一個使用請求的運算符的小演示/示例。
https://stackblitz.com/edit/rxjs-map-operators
您可以選擇間隔或單擊以發出外部可觀察值。 對於內部 observable,您可以選擇是發出間隔(3 項)還是 http 請求。
它將在選擇下方打印結果。
假設您訂閱了一個天氣頻道。 天氣播音員閱讀了經過幾次操作后傳遞給他的報告。
如果播音員正在閱讀一份報告,而在閱讀另一份報告時進來。如果他停止閱讀第一份報告並在新報告到達時立即開始閱讀,那么他正在執行switchMap
。 因為switchMap將每個源值投影到一個 observable 中,該 observable 合並在輸出 observable 中,所以僅從最近“最近”投影的 observable 中發出值。
如果廣播播音員直到第一個報告完成后才開始新報告,我們有concatMap
。 concatMap將每個源值投影到一個 observable 中,該 observable 以序列化的方式合並到輸出 observable 中,等待每個值完成后再合並下一個。
如果在播音員仍在閱讀時mergeMap/flatMap
新報告,並且他的回應是以某種方式同時閱讀兩者,那么我們就有了mergeMap/flatMap
。 ( flatMap 是 mergeMap 的別名)。 因為mergeMap將每個源值投影到一個 observable 中,該 observable 合並在輸出 observable 中。 “mergeMap”是 switchMap 和 concatMap 的更基本版本。
這是另一種思考不同類型地圖之間差異的方式。 這幫助我理解了它。 我希望它可以幫助其他人。
考慮以下來源:
為了說明不同類型地圖之間的差異,我們將把字母源中的項目鏈接到對應於該字母的“詞”源,使用每個不同的地圖來查看不同的結果。
這與其他地圖不同,因為它沒有引入另一個可觀察的來源。 它只是將傳入的值轉換為另一個值。
因此,來自小寫源的輸出,通過將輸入轉換為大寫的 Map,將是:
Input: a,b,c,d
Output: A, B, C, D
這會將每個輸入轉換為另一個源,將輸出切換為來自該新源(即訂閱該新源)。 當另一個 alpha 輸入到達時,“word”源會發生變化(我們取消訂閱之前的“word”源)。
Input: a,b,c,d
Output: animal, aardvark, bull, baker, beach, cow, dog, day, dinner
與 switchMap 類似,除了 Concat 等待每個源完成后再繼續下一個。
Input: a,b,c,d
Output: animal, aardvark, axe, bull, baker, beach, cow, car, cat, dog, day, dinner
與 Concat Map 類似,除了它在完成最后一個源時會忽略任何輸入。 下面的示例假設 alpha 輸入“b”和“d”都在前一個映射源仍在完成時傳入,因此它們被忽略。
Input: a,b,c,d
Output: animal, aardvark, axe, cow, car, cat
合並地圖(又名平面地圖)
就像 concatMap 一樣,每個源都運行到完成,但是一個新的源可以在其他源仍在運行時啟動 - 因此序列重疊。
Input: a,b,c,d
Output: animal, aardvark, bull, axe, baker, cow, car, beach, dog, day, cat, dinner
switchMap - 停止處理訂單並開始處理新訂單。 只有最新的訂單才能完成。
concatmap - 訂單被添加到隊列中。 你完成你正在處理的任何訂單。 完成訂單后,您將處理下一個訂單。
mergeMap - 一旦獲得訂單,您將同時處理所有訂單。
exhaustMap - 您忽略新訂單並完成您正在處理的任何訂單。 完成后,您可以自由接受新訂單。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.