有人请用Javascript解释SwitchMap和FlatMap之间的区别(角度透视,rxjs 5)
在我的理解中.
SwitchMap仅发出最新的可观察值并取消之前的可观察值.
faltMap收集所有单独的observable并返回单个数组中的所有observable,而不关心可观察的顺序.异步工作.
concatMap保留顺序并发出所有可观察值,同步工作
是对的吗?
如何做mergeMap从上面的工作方式不同?
有人,请举例说明.
Yil*_*maz 32
假设您订阅了天气频道。气象播音员宣读了经过多次操作后传递给他的报告。
如果播音员正在阅读一份报告,而在阅读另一份报告时进来。如果他停止阅读第一份报告并在新报告到达后立即开始阅读,那么他正在做switchMap。因为switchMap将每个源值投影到一个可观察值,该可观察值合并到输出可观察值中,所以仅从最近投影的可观察值发出值。
如果广播播音员在第一个报告完成之前才开始新的报告,那么我们有concatMap。concatMap将每个源值投影到一个可观察量,该可观察量以序列化方式合并到输出可观察量中,等待每个源值完成,然后再合并下一个。
如果在播音员仍在朗读时收到新的报告,而他的反应是同时朗读两份报告,那么我们就可以了mergeMap/flatMap。( flatMap 是 mergeMap 的别名)。因为mergeMap将每个源值投影到一个可观察量,该可观察量将合并到输出可观察量中。“mergeMap”是 switchMap 和 concatMap 的更基本版本。
Zah*_*hiC 23
下面是一个示例,说明当源是直接项(0,1,2,3,4)时每个运算符的行为,并且map函数创建一个将每个项延迟500ms的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);Run Code Online (Sandbox Code Playgroud)
.examples > div {
cursor: pointer;
background-color: #4CAF50;
color: white;
padding: 7px 16px;
display: inline-block;
}Run Code Online (Sandbox Code Playgroud)
<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>Run Code Online (Sandbox Code Playgroud)
jad*_*adc 17
这是思考不同类型地图之间差异的另一种方式。这帮助我理解了它。我希望它可以帮助其他人。
考虑以下来源:
为了说明不同类型的地图之间的差异,我们将把字母表源中的项目链接到与字母表中的字母相对应的“单词”源,使用每个不同的地图来查看不同的结果。
这与其他地图不同,因为它没有引入其他可观察源。它只是将传入值转换为另一个值。
因此,小写源的输出,通过将输入转换为大写的 Map,将是:
Input: a,b,c,d
Output: A, B, C, D
Run Code Online (Sandbox Code Playgroud)
这将每个输入转换为另一个源,将输出切换为来自该新源(即订阅该新源)。当另一个 alpha 输入到达时,“word”源会发生变化(我们取消订阅先前的“word”源)。
Input: a,b,c,d
Output: animal, aardvark, bull, baker, beach, cow, dog, day, dinner
Run Code Online (Sandbox Code Playgroud)
与 switchMap 类似,只不过 Concat 会等到每个源完成后再继续下一个。
Input: a,b,c,d
Output: animal, aardvark, axe, bull, baker, beach, cow, car, cat, dog, day, dinner
Run Code Online (Sandbox Code Playgroud)
与 Concat Map 类似,只不过它会忽略在完成最后一个源时传入的任何输入。下面的示例假设 alpha 输入“b”和“d”均在前一个映射源仍在完成时进入,因此它们被忽略。
Input: a,b,c,d
Output: animal, aardvark, axe, cow, car, cat
Run Code Online (Sandbox Code Playgroud)
合并地图(又名平面地图)
与 concatMap 一样,每个源都运行完成,但新源可以在其他源仍在运行时启动 - 因此序列重叠。
Input: a,b,c,d
Output: animal, aardvark, bull, axe, baker, cow, car, beach, dog, day, cat, dinner
Run Code Online (Sandbox Code Playgroud)
kos*_*kos 16
在下面的大理石图中,以5ms,10ms,20ms发射的源流将*映射为a timer(0, 3),限制为3种发射:
在这里玩这个大理石图:“ mergeMap vs exhaustMap vs switchMap vs concatMap”
已经有了所有这些很棒的答案,我想添加一个更直观的解释
希望对别人有帮助
Ric*_*sen 15
@ZahiC,很酷的答案-我喜欢在代码示例中使用功能组合。如果可以的话,我想借用它来说明使用定时观测的几个额外点。
这些运算符都像是转换运算符map(),其共同特征是它们具有可观察的内部和外部。关键区别在于外部可观察者控制内部可观察者的方式。
为了对比它们,我的代码示例成对运行它们,以形式输出值[outerValue,innerValue]。我为测试增加了时间间隔,并更改了内部延迟,以便时间上有一些重叠(使用的公式为delay((5-x)*200))。
这些都输出所有值,不同之处在于顺序。
mergeMap-通过内部可观察的
[0,0],[1,0],[0,1],[2,0],[1,1],[3,0],[2,1],[4]进行排序,0],[3,1],[4,1]concatMap-通过外部可观察的
[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]进行 节流exhaustMap-先按
[0,0],[0,1],[4,0],[4,1] 节气门
从输出中,switchMap会限制所有不完整的内部发射,但是exhaustMap会限制随后的发射,直到较早的内部发射完成。
我之所以这样说是因为switchmap通常用于应该真正使用mergeMap的SO答案中。
mergeMap-通过内部可观察的
[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));Run Code Online (Sandbox Code Playgroud)
.examples > div {
cursor: pointer;
background-color: #4CAF50;
color: white;
padding: 7px 16px;
display: inline-block;
}Run Code Online (Sandbox Code Playgroud)
<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>Run Code Online (Sandbox Code Playgroud)
switchMap - 停止处理订单并开始处理新订单。只有最新的订单才会完成。
concatmap - 订单被添加到队列中。您可以完成正在处理的任何订单。完成订单后,您将处理下一个订单。
mergeMap - 一旦收到所有订单,您将同时处理所有订单。
exhausMap - 您忽略新订单并完成您正在处理的任何订单。完成后,您可以自由接受新订单。
我不久前制作了一个使用请求的运算符的小演示/示例。
https://stackblitz.com/edit/rxjs-map-operators
您可以选择间隔或单击来发出外部可观察值。对于内部可观察,您可以选择是否发出间隔(3 个项目)或 http 请求。
它将在选择下方打印结果。
这在开始时有点长,至少对我来说是这样。
无论如何,考虑一下:
flatMapIS ANOTHER NAME FOR mergeMap-mergeMap方法接受一个可选参数concurrency,该参数定义可以同时订阅多少个 Observable
concatMap等于mergeMap并发设置为 1
用mergeMap你不能失去你合并的观发出任何情况下,你在你的答案建议
switchMap如您所描述的那样工作(有关更多详细信息,请参阅这篇不错的文章https://blog.angular-university.io/rxjs-switchmap-operator/)
| 归档时间: |
|
| 查看次数: |
11817 次 |
| 最近记录: |