RxJs SwitchMap 学习笔记

网址:https://www.learnrxjs.io/learn-rxjs/operators/transformation/switchmap

The main difference between switchMap and other flattening operators is the cancelling effect. On each emission the previous inner observable (the result of the function you supplied) is cancelled and the new observable is subscribed. You can remember this by the phrase switch to a new observable.

switchMap 和其他扁平化操作符的主要区别在于取消效果。 在每次发射时,先前的内部 observable(您提供的函数的结果)被取消并订阅新的 observable。 您可以通过短语 switch to a new observable 记住这一点。

This works perfectly for scenarios like typeaheads where you are no longer concerned with the response of the previous request when a new input arrives. This also is a safe option in situations where a long lived inner observable could cause memory leaks, for instance if you used mergeMap with an interval and forgot to properly dispose of inner subscriptions. Remember, switchMap maintains only one inner subscription at a time, this can be seen clearly in the first example.

这对于像预先输入这样的场景非常有效,当新输入到达时,您不再关心先前请求的响应。 在长期存在的内部 observable 可能导致内存泄漏的情况下,这也是一个安全的选择。

Be careful though, you probably want to avoid switchMap in scenarios where every request needs to complete, think writes to a database. switchMap could cancel a request if the source emits quickly enough. In these scenarios mergeMap is the correct option.

但是要小心,您可能希望在每个请求都需要完成的情况下避免使用 switchMap,比如写入数据库的场景。 如果源发出足够快,switchMap 可以取消请求。 在这些情况下,mergeMap 是正确的选项。

看这个例子:

import { interval, fromEvent } from 'rxjs';
import { switchMap } from 'rxjs/operators';

fromEvent(document, 'click')
.pipe(
  // restart counter on every click
  switchMap(() => interval(1000))
)
.subscribe(console.log);

每次点击屏幕之后,fromEvent issue 出来的 MouseEvent,传入 switchMap 内部,都会重启一个新的时间间隔为1秒的计时器,并且取消之前的定时器。打印如下:

再看一个实现定时器的例子:

import { Component, OnInit } from '@angular/core';
import { interval, fromEvent, merge, empty } from 'rxjs';
import { switchMap, scan, takeWhile, startWith, mapTo } from 'rxjs/operators';

const COUNTDOWN_SECONDS = 1000;

@Component({
  selector: 'switchMap-study',
  templateUrl: './switchMap.component.html'
})
export class SwitchMapComponent implements OnInit {
    ngOnInit(): void {

    // elem refs
    const remainingLabel = document.getElementById('remaining');
    const pauseButton = document.getElementById('pause');
    const resumeButton = document.getElementById('resume');

    // streams
    const interval$ = interval(1000).pipe(mapTo(-1));
    const pause$ = fromEvent(pauseButton, 'click').pipe(mapTo(false));
    const resume$ = fromEvent(resumeButton, 'click').pipe(mapTo(true));

    const timer$ = merge(pause$, resume$).pipe(
        startWith(true),
        switchMap(val => (val ? interval$ : empty())),
        scan((acc, curr) => (curr ? curr + acc : acc), COUNTDOWN_SECONDS),
        takeWhile(v => v >= 0)).subscribe((val: any) => (remainingLabel.innerHTML = val));
    }
}
<h1>Switch Map Study</h1>

<a href="https://www.learnrxjs.io/learn-rxjs/operators/transformation/switchmap">Document</a>

<h4>
    Time remaining: <span id="remaining"></span>
    </h4>
    <button id="pause">
    Pause Timer
    </button>
    <button id="resume">
    Resume Timer
</button>

刚开始时,startWith true,因此 switchMap 得以继续下去。switchMap 传入的 project,接受的参数 val 是 boolean 类型,返回一个新的 Observable,即 internal$.

注意 empty() 的用法,返回一个类型为 never 的 Observable.

Creates an Observable that emits no items to the Observer and immediately emits a complete notification.
Just emits 'complete', and nothing else.
This static operator is useful for creating a simple Observable that only emits the complete notification. It can be used for composing with other Observables, such as in a mergeMap.

单步调试点了 pause 之后:

第 41 行 unsubscribe 方法,体现了 switchMap 自动取消先前的内部 observable 的特性:

先 cancel,再订阅新的 Observable:

如果返回 empty,就不会再执行后续的 scan 了:

可以把 switchMap 输入参数,即 projection 进行改造:

该 projection 的类型是一个箭头函数,输入参数是一个 boolean,输出是一个新的 Observable.

(0)

相关推荐

  • 程序猿的今日头条面试历险记(一)

    FIN 介绍 上图是小姐姐旅行过程中拍的风景图.先来介绍下今天的女主角,毕业自中科大研究生,拿了一大堆大厂的 offer.这次的面试是小姐姐在云南旅行中进行的,目前已经完成了二面,今天这篇文章是对一面 ...

  • 一则公报案例学习笔记:对修改股东出资期限应否适用资本多数决规则的思考|审判研究

    一.问题的提出 2021年第3期<最高人民法院公报案例>刊登了鸿大(上海)投资管理有限公司与姚锦城公司决议纠纷上诉案,裁判要旨为:"公司股东滥用控股地位,以多数决方式通过修改出资 ...

  • JAVA多线程学习笔记整理

    多线程: 三种创建方法 继承Thread类,以线程运行内容重写run方法,创建Thread对象并用start方法启动该线程. (匿名内部类) (Lambda表达式) 实现Runable接口,以线程运行 ...

  • 周哥学习笔记(2021.5.8)

    心理界限存在的意义,正是为了帮助人们控制情绪进入的量,不至于太过冷漠或太过投入,让我们保持一个合适的距离与外界互动. 人没有办法只通过吸收变得更美好和丰富,它必须通过大胆的碰撞和创造.如果不能保持足够 ...

  • 【学习笔记】控制角色移动的N种方法,但都离不开重复执行

    [学习笔记]控制角色移动的N种方法,但都离不开重复执行 今天我们讲一下控制角色移动的多种方法,因为缺少操作实例,希望课下同学们结合例子好好练习. 首先,我们说一下控制角色移动的多种方法.最比较常见的就 ...

  • 胡希恕伤寒论学习笔记——42

    42.太阳病,外证未解,脉浮弱者,当以汗解,宜桂枝汤. 字面意思是说:太阳病,外证依然存在,脉是浮弱的,治疗上依然需要通过出汗的方法,这时应该用桂枝汤一类的方剂. "宜"字说明不是 ...

  • 量柱擒涨停 - 量柱战法学习笔记(2)

    四.倍量战术 1.倍量的理解 [形态特征]:与前一个交易日比较高出1倍或1倍以上,就是倍量(4倍以上为发烧柱) ; [本质特征]:体现主力强势态度,主动(倍量阳/阴)买/卖盘吸筹坚决; [位置性质]: ...

  • 胡希恕伤寒论学习笔记——43

    43.太阳病,下之微喘者,表未解故也,桂枝加厚朴杏子汤主之. 桂枝加厚朴杏子汤方 桂枝三两 芍药三两 厚朴二两(炙,去皮) 杏仁五十枚(去皮尖)甘草二两(炙) 生姜三两(切)大枣十二枚(掰) 上七味, ...

  • 学习笔记:信息技术

    学习笔记:信息技术

  • 安全学习笔记

    安全学习笔记