RxJs SwitchMap 学习笔记

大厂光环
• 阅读 2724

网址:https://www.learnrxjs.io/lear...

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秒的计时器,并且取消之前的定时器。打印如下:

RxJs SwitchMap 学习笔记

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

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>

RxJs SwitchMap 学习笔记

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

RxJs SwitchMap 学习笔记

RxJs SwitchMap 学习笔记

注意 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 之后:

RxJs SwitchMap 学习笔记

RxJs SwitchMap 学习笔记

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

RxJs SwitchMap 学习笔记

RxJs SwitchMap 学习笔记

先 cancel,再订阅新的 Observable:
RxJs SwitchMap 学习笔记

如果返回 empty,就不会再执行后续的 scan 了:
RxJs SwitchMap 学习笔记

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

RxJs SwitchMap 学习笔记

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

RxJs SwitchMap 学习笔记

更多Jerry的原创文章,尽在:"汪子熙":
RxJs SwitchMap 学习笔记

点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
7个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Easter79 Easter79
3年前
swap空间的增减方法
(1)增大swap空间去激活swap交换区:swapoff v /dev/vg00/lvswap扩展交换lv:lvextend L 10G /dev/vg00/lvswap重新生成swap交换区:mkswap /dev/vg00/lvswap激活新生成的交换区:swapon v /dev/vg00/lvswap
Jacquelyn38 Jacquelyn38
4年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
Java获得今日零时零分零秒的时间(Date型)
publicDatezeroTime()throwsParseException{    DatetimenewDate();    SimpleDateFormatsimpnewSimpleDateFormat("yyyyMMdd00:00:00");    SimpleDateFormatsimp2newS
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Python进阶者 Python进阶者
1年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这