5|5 张弹珠图彻底弄清 RxJS 的拉平策略(mergeMap、switchMap、concatMap、exhaustMap)
RxJS 的操作符理解起来确实比较复杂,比如最常用的几种 map 操作符,本篇就来使劲冲一冲它们!!
文章图片
- 原创文章,非商业转载请说名出处
map 操作想必大家一定不陌生:
const { of } = Rx;
const { map} = RxOperators;
const namesObservable = of('A', 'B');
namesObservable.pipe(
map(name => `map ${name}`)
)namesObservable .subscribe(result => console.log(`${result}`))// map A
// map B
很直观,因为 map 映射的是“值”,所以足够简单~
但是,如果说,map 映射的是 observable 呢 ?
const { of } = Rx;
const { map } = RxOperators;
const namesObservable = of('A', 'B');
const http =(name)=>{
return of(`${name} 1`,`${name} 2`);
}namesObservable.pipe(
map(name => http(name))
)namesObservable.subscribe(result => console.log(`${result}`))// 则会得到两个 observable 对象
// ****observable{ .. }
// observable{ .. }
我们在 [](https://rxviz.com/)https://rxviz.com/ 的弹珠图中,可以清晰的看到:返回的仍是 observable
文章图片
【5|5 张弹珠图彻底弄清 RxJS 的拉平策略(mergeMap、switchMap、concatMap、exhaustMap)】并且 observable 由最初的 1 个,变成了 2 个(圆圈就是 observable),数据仍在里面没有被订阅解析出来。
虽然,我们可以用粗暴的方法,在订阅
.subscribe
里面再次调用订阅 .subscribe
,则可得值:const { of } = Rx;
const { map } = RxOperators;
const namesObservable = of('A', 'B');
const http =(name)=>{
return of(`${name} 1`,`${name} 2`);
}namesObservable.pipe(
map(name => http(name))
)namesObservable .subscribe(resultObservable => {
resultObservable.subscribe(result => console.log(`${result}`) )
})// A1
// A2
// B1
// B2
但是,这样包裹写法注定是不优雅的,所以,为了解决这个差异,RxJS 引入了 —— Flattening(扁平化)策略!!
我们可以借助 flatMap 操作符,则能得到同样的解析值的效果~
flatMap 其实也就是我们熟知的 mergeMap 操作符;
代码如下:
const { of } = Rx;
const { mergeMap} = RxOperators;
const namesObservable = of('A', 'B');
const http =(name)=>{
return of(`${name} 1`,`${name} 2`);
}namesObservable.pipe(
mergeMap(name => http(name))
)namesObservable.subscribe(result => console.log(`${result}`))
// A1
// A2
// B1
// B2
更进一步,沿着这种偏平化策略的思路,除了 mergeMap,RxJS 又引入了 switchMap、concatMap 和 exhaustMap,它们能够提供不同方向的拉平策略。
我们再借助 [](https://rxviz.com/)https://rxviz.com/ 的弹珠图,一眼便能看到它们的差异:
设置一个定时器,每一秒都发出一个 observable,一共发 3 次,来看下分别得值;
- mergeMap
const { of,interval} = Rx;
const { mergeMap,take,map } = RxOperators;
const namesObservable = of('A', 'B');
const http =(name)=>{
return interval(1000)
.pipe(
take(3),
map(()=>of(`${name} 1`,`${name} 2`))
)
}namesObservable.pipe(
mergeMap(name => http(name))
)
文章图片
mergeMap
会同时维护多个活动的内部订阅;- switchMap
const { of,interval} = Rx;
const { switchMap,take,map } = RxOperators;
const namesObservable = of('A', 'B');
const http =(name)=>{
return interval(1000)
.pipe(
take(3),
map(()=>of(`${name} 1`,`${name} 2`))
)
}namesObservable.pipe(
switchMap(name => http(name))
)
文章图片
switchMap
,在每次发出时,会取消前一个内部 observable 的订阅,然后订阅一个新的 observable;- concatMap
const { of,interval} = Rx;
const { concatMap ,take,map } = RxOperators;
const namesObservable = of('A', 'B');
const http =(name)=>{
return interval(1000)
.pipe(
take(3),
map(()=>of(`${name} 1`,`${name} 2`))
)
}namesObservable.pipe(
concatMap (name => http(name))
)
文章图片
concatMap
会在之前前一个内部 observable 完成后,才会订阅下一个;- exhaustMap
const { of,interval} = Rx;
const { exhaustMap ,take,map } = RxOperators;
const namesObservable = of('A', 'B');
const http =(name)=>{
return interval(1000)
.pipe(
take(3),
map(()=>of(`${name} 1`,`${name} 2`))
)
}namesObservable.pipe(
exhaustMap (name => http(name))
)
文章图片
exhaustMap
映射成内部 observable,忽略其他值直到该 observable 完成;OK,以上便是本篇分享。
觉得不错点个赞吧,您的鼓励,我的动力,坚持输出质量好文~~ 欢迎评论讨论
我是掘金安东尼,输出暴露输入,技术洞见生活。再会吧~~
推荐阅读
- 5 张弹珠图彻底弄清 RxJS 的拉平策略(mergeMapswitchMapconcatMapexhaustMap)
- 这张磁盘有写保护,本文教您磁盘被写保护怎样办
- 微信怎么发100张照片给朋友
- 苹果手机怎样拼图多张照片
- Android如何添加多张引导页
- 如何将多张图片合成mp4视频格式,并加入背景音乐...
- 又一位大佬「归隐」,张勇卸任淘宝天猫董事长,管理者又该如何应对()
- 安卓手机上传同一张图片第二次不触发onchange
- 直击股东大会|红旗连锁党委书记、董事长曹世如:肩负重责 质量扩张稳中求胜 | 直击股东会
- oracle 从一张表的数据复制到另一张表中mapper.xml