flatMap, mergeMap, switchMap and concatMap in rxjs?
有人,请用Javascript解释SwitchMap和FlatMap之间的区别(角度角度,rxjs 5)
以我的理解。
SwitchMap仅发出最新的可观察值,并取消先前的可观察值。
flatMap收集所有单个可观测值,并在单个数组中返回所有可观测值,而无需关心可观测的顺序。 异步工作。
concatMap保留顺序并发出所有可观察的值,同步工作
那正确吗?
mergeMap与上面的工作原理有何不同?
有人,请举例说明。
从先前的答案中得出:
- flatMap / mergeMap-立即为任何源项目创建一个Observable,所有先前的Observable均保持活动状态
- concatMap-在创建下一个Observable之前等待其完成
- switchMap-对于任何源项目,完成上一个Observable并立即创建下一个
- exhaustMap-在前一个Observable未完成时将忽略源项目
这是一个示例,说明当源为直接项目(0,1,2,3,4)时,每个运算符的行为。map函数创建一个Observable,将每个项目延迟500ms:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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); |
1 2 3 4 5 6 7 | .examples > div { cursor: pointer; background-color: #4CAF50; color: white; padding: 7px 16px; display: inline-block; } |
1 2 3 4 5 6 7 8 | <script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.8/Rx.js"> mergeMap flatMap concatMap switchMap exhaustMap |
在下面的大理石图中,以5ms,10ms,20ms发射的源流将被*映射为
在这里玩这个大理石图:" mergeMap vs exhaustMap vs switchMap vs concatMap"
已经有了所有这些很棒的答案,我想添加一个更直观的解释
希望对别人有帮助
@ZahiC,很酷的答案-我喜欢在代码示例中使用功能组合。如果可以的话,我想借用它来说明使用定时观测的几个额外点。
外部,内部和控制
这些运算符都是像
为了对比它们,我的代码示例成对运行它们,以
mergeMap vs concatMap
这些都输出所有值,不同之处在于顺序。
mergeMap - Order by inner observable
[0,0],[1,0],[0,1],[2,0],[1,1],[3,0],[2,1],[4,0],[3,1],[4,1]concatMap - Order by outer observable
[0,0],[0,1],[1,0],[1,1],[2,0],[2,1],[3,0],[3,1],[4,0],[4,1]
从输出中,可以在序列中延迟mergeMap外部发射,但是concatMap遵循严格的外部发射序列。
switchMap vs exhaustMap
这些都限制输出。
switchMap - Throttle by last
[3,0],[4,0],[4,1]exhaustMap - Throttle by first
[0,0],[0,1],[4,0],[4,1]
从输出中,switchMap会限制所有不完整的内部发射,但是exhaustMap会限制随后的发射,直到较早的内部发射完成。
mergeMap vs switchMap
我之所以这样说是因为switchmap通常用于应该真正使用mergeMap的SO答案中。
mergeMap - Order by inner observable
[0,0],[1,0],[0,1],[2,0],[1,1],[3,0],[2,1],[4,0],[3,1],[4,1]switchMap - Throttle by last
[3,0],[4,0],[4,1]
主要结论是switchMap输出取决于内部可观察到的时间是不可预测的,例如,如果内部是http,则结果可以取决于连接速度。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | 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)); |
1 2 3 4 5 6 7 | .examples > div { cursor: pointer; background-color: #4CAF50; color: white; padding: 7px 16px; display: inline-block; } |
1 2 3 4 5 6 | <script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.8/Rx.js"> mergeMap vs concatMap switchMap vs exhaustMap mergeMap vs switchMap |
至少对于我来说,这刚开始需要很长时间。
无论如何,请考虑以下几点:
使用
我做了一个使用请求的运算符的演示/示例。
您可以选择一个间隔或单击以发出外部可观察值。
对于内部可观察对象,您可以选择发出间隔(3个项目)还是发出HTTP请求。
它将在选择下方打印结果。