网站首页 > 知识剖析 正文
switchMap 操作符通过名字便知和 mergeMap 很像,是用来处理嵌套流的。而它们之间的不同之处在于,switchMap 会先查看是否有“内部”订阅,如果有,switchMap 会先取消这个“内部”订阅,再对接收到的值做处理。
文字描述可能还不让你理解,我们再用代码来演示下它们的不同。
fromEvent(document, "click").pipe(
scan(i => i + 1, 0),
switchMap(value => of(value).pipe(delay(500))) // 在这行代码分别使用 mergeMap 和 switchMap
)
.subscribe(value => {
console.log(value);
});
首先使用 mergeMap,在页面上连续点击 5 次,控制台将输出 1 2 3 4 5。也就是说每次点击产生的值都会被 mergeMap 处理。再来看看 switchMap,在页面上连续点击 5 次后,我们发现控制台只输出了一次,值为 5。这就是我们在文章开头说的,switchMap 每接收到新值时会检查之前有没有发生过订阅,如果有,先取消,再处理新值。由于示例代码中有 500 毫秒的延迟,只要比我们点击页面的速度慢,导致 2 3 4 5 次点击都会先取消上一次点击事件流下来的事件,再处理本次事件,由于第五次点击后面没有事件了,所以输出了 5。这就是 switchMap 的工作机理。
了解了 switchMap 的工作方式,我们就可以来写代码实现它了。首先拷贝之前写好的 MyMergeMap 代码:
class MySwitchMapSubscriber extends Subscriber {
constructor(sub, fn) {
super(sub);
this.fn = fn;
}
_next(value) {
const innerObservable$ = this.fn(value);
innerObservable$.subscribe(value => {
this.destination.next(value);
});
}
}
const mySwitchMap = fn => source => {
return source.lift({
call(sub, source) {
source.subscribe(new MySwitchMapSubscriber(sub, fn));
}
});
};
下面我们来改造代码。根据我们了解到的 switchMap 的工作机理,首先我们要有内部订阅对象,这是由 innerObservable$.subscribe 这段代码产生的。然后我们在这段代码执行前对这个内部订阅对象进行检查,如果有值,说明有过订阅,就 unsubscribe 它。修改后代码如下:
class MySwitchMapSubscriber extends Subscriber {
constructor(sub, fn) {
super(sub);
this.fn = fn;
this.innerSubscription = null;
}
_next(value) {
const innerObservable$ = this.fn(value);
if (this.innerSubscription) {
this.innerSubscription.unsubscribe();
}
this.innerSubscription = innerObservable$.subscribe(value => {
this.destination.next(value);
});
}
}
const mySwitchMap = fn => source => {
return source.lift({
call(sub, source) {
source.subscribe(new MySwitchMapSubscriber(sub, fn));
}
});
};
我们在 MySwitchMapSubscriber 自定义类的构造函数中,创建了成员变量 innerSubscription,用来保存内部订阅对象的值。然后我们在订阅内部对象前,加入了代码检查这个成员变量是否有值,有值就 unsubscribe 它。这样自制版的 switchMap 操作符就完成了。是不是很简单?它和 mergeMap 操作符的区别可以说只有一行代码之差。假设示例代码的每次点击都和一个 http 请求关联,这种场景该用 mergeMap 还是 switchMap 呢?留给大家去思考吧。
如有任何问题,请添加微信公众号“读一读我”。
猜你喜欢
- 2024-11-14 vue.js正确使用百度地图的方案 vue百度地图自定义控件
- 2024-11-14 七爪源码:如何在 JavaScript 中将 JSON 转换为地图
- 2024-11-14 在地图上创建热力图的方法 怎么用热力图选址
- 2024-11-14 快速了解 ES6 的Map与WeakMap es6 map使用场景
- 2024-11-14 Vue3 + TS + Leafletjs 打造企业级原神大地图
- 2024-11-14 好东西一起用,Cesium.js真是让3D地图尖叫的神奇框架!
- 2024-11-14 为 Next.js 项目创建站点地图文件
- 2024-11-14 JavaScript 轻松获取 Map 中的某个 key
- 2024-11-14 何时使用 Map 来代替普通的 JS 对象
- 2024-11-14 看了几十篇论文实现了个专业算法,用threejs做了个人员定位系统
- 最近发表
- 标签列表
-
- xml (46)
- css animation (57)
- array_slice (60)
- htmlspecialchars (54)
- position: absolute (54)
- datediff函数 (47)
- array_pop (49)
- jsmap (52)
- toggleclass (43)
- console.time (63)
- .sql (41)
- ahref (40)
- js json.parse (59)
- html复选框 (60)
- css 透明 (44)
- css 颜色 (47)
- php replace (41)
- css nth-child (48)
- min-height (40)
- xml schema (44)
- css 最后一个元素 (46)
- location.origin (44)
- table border (49)
- html tr (40)
- video controls (49)