有人,请解释一下SwitchMap和FlatMap在Javascript方面的区别(在角度透视图中,rxjs 5)
以我的理解。
SwitchMap仅发出最新的可观察值,并取消先前的可观察值。
flatMap收集所有单独的可观测数据,并在单个数组中返回所有可观测数据,而不关心可观测数据的顺序。异步工作。
concatMap保持秩序并发出所有可观察值,同步工作
是这样吗?
mergeMap与上面的工作方式有什么不同?
有人,请举例说明。
@ZahiC,很酷的回答-我喜欢在代码示例中使用函数组合。如果可以的话,我想借用它来说明几个额外的点使用定时观测。
这些操作符都是变换操作符,比如map()
,它们的共同特点是具有外部和内部可观察性。关键的区别在于外部可观察物控制内部可观察物的方式。
为了对比它们,我的代码示例成对运行它们,以[outerValue, innerValue]
的形式输出值。我在测试中添加了间隔,并更改了内部延迟,以便在定时上有一些重叠(使用的公式是延迟((5-x)*200)
)。
这两个都输出所有值,区别在于顺序。
合并映射-内部可观测的顺序
[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遵循严格的外部发射序列。
这两个节流输出。
开关图-最后一次节流
[3,0],[4,0],[4,1]
排气图-通过第一个节气门
[0,0],[0,1],[4,0],[4,1]
我加入这个是因为切换映射经常用于SO答案中,在这些答案中应该使用真正的合并映射。
合并映射-内部可观测的顺序
[0,0],[1,0],[0,1],[2,0],[1,1],[3,0],[2,1],[4,0],[3,1],[4,1]
开关图-最后一次节流
[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>
在下面的大理石图中,以5ms、10ms、20ms发射的源流将*映射到计时器(0,3)
,限制为3次发射:
在这里玩这个大理石图:“合并地图vs用尽地图vs切换地图vs连接地图”
已经有了这些令人敬畏的答案,我想添加一个更直观的解释
希望对某人有所帮助
根据之前的回答:
下面是一个示例,说明了当源为立即项(0,1,2,3,4)且映射函数创建一个可观测项时,每个操作符的行为方式,该项可观测项将延迟500毫秒:
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>
我们有一个执行http请求的请求服务。所有请求都实现IRequest接口,该接口包含http方法和一个执行函数,该函数依次返回另一个可观察的对象。 RequestService有一个重载,它接受一个源可观察对象,还有一个requestfactory,它根据源可观察对象的值返回一个IRequest实例。 当然,在服务中做了更多的工作(日志记录、默认错误处理,...),但大多数与问题无关。 现在,这一
switchmap的rxjava文档定义相当模糊,它链接到与FlatMap相同的页面。这两个操作员有什么不同?
我正在努力理解rxJs中的平面图和连续图之间的区别。 我能理解的最清楚的答案是concatmap和flatmap之间的区别 所以我自己去试了试。 我用这里的操场操场作为例子 问题 1)根据我的理解,平面图的使用应该混合输出,这样控制台日志就像(1,3,2,4,5)。我尝试了30多次,总是出现在同一行(1, 2, 3, 4, 5) 我做错了什么,或者我做错了什么? 2)如果在和上删除注释并包含包含多
当我使用Angular HttpClient发出GET请求时,我得到一个可观察的返回,并在RxJS操作符mergeMap中处理它。 现在一次又一次地抛出404,我想抓住它。最后,浏览器控制台中不应出现错误消息,并且应使用流的下一个值处理管道。 这有可能吗?我没有用catchError()管理它。 以下是我的代码的简化版本: 更新:添加了带有catchError()的方法 我尝试过这种方式,但没有检
我有一条可以观察到的溪流。第一个运算符是一个mergeMap,它返回一个可观察的数组。然后,我必须有第二个mergeMap从第一个mergeMap的返回中获取最终值。我觉得这第二个合并映射应该是不必要的,但找不到绕过它的方法。 例子: 这最终是我所拥有的。第二个mergeMap只存在于订阅第一个的输出。没有它,我的输出是可观察的(即(1)的
我有以下方法: 和批准的排放方法: 我得到这样的错误,当我试图链我的rxjs请求: [at loader]中出错/src/app/auth/intercept/auth。拦截器。ts:18:16 TS2345:类型为“(res:any)的参数= 如何正确链接此请求?不要同时使用平面贴图链。map()和。error()方法?我可以用这种方式链接请求吗?因为我需要从我的请求方法(其自定义Http实现)