有人请用Javascript解释SwitchMap和FlatMap之间的区别(角度透视,rxjs 5)
根据我的理解。
SwitchMap 仅发出最新的可观察值并取消之前的可观察值。
faltMap 收集所有单独的observable并返回单个数组中的所有observable,而不关心可观察的顺序。异步工作。
concatMap 保留顺序并发出所有可观察值,同步工作
是吗?
mergeMap 与上面的工作原理有何不同?
有人,请举例说明。答案 0 :(得分:11)
下面是一个示例,说明当源是直接项(0,1,2,3,4)时每个运算符的行为,并且map函数创建一个将每个项延迟500ms的Observable:
updateChildren(...)
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;
}
答案 1 :(得分:5)
@ ZahiC,很酷的回答 - 我喜欢在代码示例中使用功能组合。如果我愿意,可以借用它来说明使用定时观察的几个额外点。
这些运算符都是transformation operators,如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]
排气地图 - 首先加油 [0,0],[0,1],[4,0],[4,1]
从输出中,switchMap限制任何不完整内部发射,但排除后面的限制,直到先前的完成。
我把它扔进去是因为switchmap经常用在SO答案中,其中应该使用mergeMap。
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 get ,结果可能取决于连接速度。
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>
&#13;
答案 2 :(得分:2)
至少在我看来,这一开始有点长,
无论如何,请考虑一下:
flatMap
mergeMap
的另一个名称 - mergeMap
方法接受一个可选参数concurrency
,该参数定义了可以同时订阅的Observable数量
concatMap
等于mergeMap
且并发设置为1
mergeMap
你不会丢失你正在按照你在答案中的建议合并的Observable所发出的任何事件
switchMap
按照您的描述工作(有关详细信息,请参阅此文章https://blog.angular-university.io/rxjs-switchmap-operator/)
答案 3 :(得分:2)
在下面的大理石图中,以 *映射的源流以 5ms , 10ms , 20ms 发射>到timer(0, 3)
,限制为3种排放:
在此处使用此大理石图:"mergeMap vs exhaustMap vs switchMap vs concatMap"
已经有了所有这些出色的答案,我想添加一个更直观的解释
希望它对某人有帮助
答案 4 :(得分:2)
这是思考不同类型地图之间差异的另一种方法。这帮助我绕开了头脑。我希望它可以帮助其他人。
请考虑以下来源:
为说明不同类型的地图之间的区别,我们将使用每个不同的地图查看从不同字母到对应于该字母字母的“单词”源的条目。
这与其他地图不同,因为它没有引入其他可观测的来源。它将输入的值转换为另一个值。
因此,通过将输入转换为大写的Map的小写源的输出将是:
Input: a,b,c,d
Output: A, B, C, D
这会将每个输入转换为另一个源,将输出切换为来自该新源(即订阅该新源)。当另一个Alpha输入到达时,“单词”源将发生变化(我们取消订阅先前的“单词”源)。
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
Merge Map(又称平面地图)
就像concatMap一样,每个源都可以运行完成,但是在其他源仍在运行时可以启动一个新源-因此序列重叠。
Input: a,b,c,d
Output: animal, aardvark, bull, axe, baker, cow, car, beach, dog, day, cat, dinner
答案 5 :(得分:0)
前段时间,我做了一个使用请求的运算符的演示/示例。
https://stackblitz.com/edit/rxjs-map-operators
您可以选择一个间隔或单击以发出外部可观察值。 对于内部可观察对象,您可以选择发出间隔(3个项目)还是发出http请求。
它将在选择内容下方打印结果。