首页 > 其他分享 >30 天精通 RxJS (17):Observable Operators - switch, mergeAll, concatAll

30 天精通 RxJS (17):Observable Operators - switch, mergeAll, concatAll

时间:2024-04-13 23:33:06浏览次数:25  
标签:concatAll Observable console 17 observable Rx ---- click

RxJS Logo

今天我们要讲三个 operators,这三个 operators 都是用来处理 Higher Order Observable。

所谓的 Higher Order Observable 就是指一个 Observable 送出的元素还是一个 Observable,就像是二维数组一样,一个数组中的每个元素都是数组。如果用泛型来表达就像是

Observable<Observable<T>>

通常我们需要的是第二层 Observable 送出的元素,所以我们希望可以把二维的 Observable 改成一维的,像是下面这样

Observable<Observable<T>> => Observable<T>

其实想要做到这件事有三个方法 switch、mergeAll 和 concatAll,其中 concatAll 我们在之前的文章已经稍微讲过了,今天这篇文章会讲解这三个 operators 各自的效果跟差异。

Operators

concatAll

我们在讲简易拖拽的示例时就有讲过这个 operator,concatAll 最重要的重点就是他会处理完前一个 observable 才会在处理下一个 observable,让我们来看一个示例

var click = Rx.Observable.fromEvent(document.body, 'click')
var source = click.map((e) => Rx.Observable.interval(1000))

var example = source.concatAll()
example.subscribe({
	next: (value) => {
		console.log(value)
	},
	error: (err) => {
		console.log('Error: ' + err)
	},
	complete: () => {
		console.log('complete')
	},
})
// (点击后)
// 0
// 1
// 2
// 3
// 4
// 5 ...

上面这段代码,当我们点击画面时就会开始送出数值,如果用 Marble Diagram 表示如下

click  : ---------c-c------------------c--.. 
        map(e => Rx.Observable.interval(1000))
source : ---------o-o------------------o--..
                   \ \
                    \ ----0----1----2----3----4--...
                     ----0----1----2----3----4--...
                     concatAll()
example: ----------------0----1----2----3----4--..

从 Marble Diagram 可以看得出来,当我们点击一下 click 事件会被转成一个 observable 而这个 observable 会每一秒送出一个递增的数值,当我们用 concatAll 之后会把二维的 observable 摊平成一维的 observable,但 concatAll 会一个一个处理,一定是等前一个 observable 完成(complete)才会处理下一个 observable,因为现在送出 observable 是无限的永远不会完成(complete),就导致他永远不会处理第二个送出的 observable!

我们再看一个例子

var click = Rx.Observable.fromEvent(document.body, 'click')
var source = click.map((e) => Rx.Observable.interval(1000).take(3))

var example = source.concatAll()
example.subscribe({
	next: (value) => {
		console.log(value)
	},
	error: (err) => {
		console.log('Error: ' + err)
	},
	complete: () => {
		console.log('complete')
	},
})

现在我们把送出的 observable 限制只取前三个元素,用 Marble Diagram 表示如下

click  : ---------c-c------------------c--.. 
        map(e => Rx.Observable.interval(1000))
source : ---------o-o------------------o--..
                   \ \                  \
                    \ ----0----1----2|   ----0----1----2|
                     ----0----1----2|
                     concatAll()
example: ----------------0----1----2----0----1----2--..

这里我们把送出的 observable 变成有限的,只会送出三个元素,这时就能看得出来 concatAll 不管两个 observable 送出的时间多么相近,一定会先处理前一个 observable 再处理下一个。

switch

switch 同样能把二维的 observable 摊平成一维的,但他们在行为上有很大的不同,我们来看下面这个示例

var click = Rx.Observable.fromEvent(document.body, 'click')
var source = click.map((e) => Rx.Observable.interval(1000))

var example = source.switch()
example.subscribe({
	next: (value) => {
		console.log(value)
	},
	error: (err) => {
		console.log('Error: ' + err)
	},
	complete: () => {
		console.log('complete')
	},
})

用 Marble Diagram 表示如下

click  : ---------c-c------------------c--.. 
        map(e => Rx.Observable.interval(1000))
source : ---------o-o------------------o--..
                   \ \                  \----0----1--...
                    \ ----0----1----2----3----4--...
                     ----0----1----2----3----4--...
                     switch()
example: -----------------0----1----2--------0----1--...

switch 最重要的就是他会在新的 observable 送出后直接处理新的 observable 不管前一个 observable 是否完成,每当有新的 observable 送出就会直接把旧的 observable 退订(unsubscribe),永远只处理最新的 observable!

所以在这上面的 Marble Diagram 可以看得出来第一次送出的 observable 跟第二次送出的 observable 时间点太相近,导致第一个 observable 还来不及送出元素就直接被退订了,当下一次送出 observable 就又会把前一次的 observable 退订。

mergeAll

我们之前讲过 merge 他可以让多个 observable 同时送出元素,mergeAll 也是同样的道理,它会把二维的 observable 转成一维的,并且能够同时处理所有的 observable,让我们来看这个示例

var click = Rx.Observable.fromEvent(document.body, 'click')
var source = click.map((e) => Rx.Observable.interval(1000))

var example = source.mergeAll()
example.subscribe({
	next: (value) => {
		console.log(value)
	},
	error: (err) => {
		console.log('Error: ' + err)
	},
	complete: () => {
		console.log('complete')
	},
})

上面这段代码用 Marble Diagram 表示如下

click  : ---------c-c------------------c--.. 
        map(e => Rx.Observable.interval(1000))
source : ---------o-o------------------o--..
                   \ \                  \----0----1--...
                    \ ----0----1----2----3----4--...
                     ----0----1----2----3----4--...
                     switch()
example: ----------------00---11---22---33---(04)4--...

从 Marble Diagram 可以看出来,所有的 observable 是并行(Parallel)处理的,也就是说 mergeAll 不会像 switch 一样退订(unsubscribe)原先的 observable 而是并行处理多个 observable。以我们的示例来说,当我们点击越多下,最后送出的频率就会越快。

另外 mergeAll 可以传入一个数值,这个数值代表他可以同时处理的 observable 数量,我们来看一个例子

var click = Rx.Observable.fromEvent(document.body, 'click')
var source = click.map((e) => Rx.Observable.interval(1000).take(3))

var example = source.mergeAll(2)
example.subscribe({
	next: (value) => {
		console.log(value)
	},
	error: (err) => {
		console.log('Error: ' + err)
	},
	complete: () => {
		console.log('complete')
	},
})

这里我们送出的 observable 改成取前三个,并且让 mergeAll 最多只能同时处理 2 个 observable,用 Marble Diagram 表示如下

click  : ---------c-c----------o----------.. 
        map(e => Rx.Observable.interval(1000))
source : ---------o-o----------c----------..
                   \ \          \----0----1----2|     
                    \ ----0----1----2|  
                     ----0----1----2|
                     mergeAll(2)
example: ----------------00---11---22---0----1----2--..

当 mergeAll 传入参数后,就会等处理中的其中一个 observable 完成,再去处理下一个。以我们的例子来说,前面两个 observabel 可以被并行处理,但第三个 observable 必须等到第一个 observable 结束后,才会开始。

我们可以利用这个参数来决定要同时处理几个 observable,如果我们传入 1 其行为就会跟 concatAll 是一模一样的,这点在原始码可以看到他们是完全相同的。

今日小结

今天介绍了三个可以处理 High Order Observable 的方法,并讲解了三个方法的差异,不知道读者有没有收获呢? 如果有任何问题欢迎在下方留言给我,感谢

本系列仅作为学习记录所用,摘录自30 天精通 Rxjs!强烈推荐!膜拜大佬!

标签:concatAll,Observable,console,17,observable,Rx,----,click
From: https://www.cnblogs.com/xiaojiuwow/p/18133580

相关文章

  • 25天【代码随想录算法训练营34期】第七章 回溯算法part02 ( ● 216.组合总和III ● 17
    **216.组合总和III**classSolution:defcombinationSum3(self,k:int,n:int)->List[List[int]]:result=[]self.backtracking(k,n,1,[],result,n)returnresultdefbacktracking(self,k,n,startingIndex,path,result,......
  • 2017第二届广东省强网杯线上赛- who are you
    2017第二届广东省强网杯线上赛whoareyou:题目类型:web题目描述:打开链接,得到一个页面:解题方法:这句话的意思说:对不起,你没有权限,先查看一下网页源码,没有发现什么有用的信息,然后再扫描一下目录:然后访问一下这几个目录,发现都不行,返回的都是:对不起,你没有权限用bp来抓包看一下:......
  • CF1788F XOR, Tree, and Queries
    CF1788FXOR,Tree,andQueries边权转点权+染色+构造首先对于限制,可以转化。设\(f_u\)表示\(1\)到\(u\)的异或和,那么限制\((u,v,w)\)就可以表示为\(f_u\oplusf_v=w\)。也就意味这如果我们将限制\((u,v,w)\)连边,要考虑的就变成\(f_u\)的赋值问题。这一步将边权转......
  • “百度杯”CTF比赛 2017 二月场-爆破-3
    “百度杯”CTF比赛2017二月场爆破-3题目类型:web题目描述:打开靶机,得到一段php代码,说明这是一道php代码审计类型的题:<?phperror_reporting(0);session_start();require('./flag.php');if(!isset($_SESSION['nums'])){$_SESSION['nums']=0;$_SESSION['time�......
  • 30 天精通 RxJS (16):Observable Operators - catch, retry, retryWhen, repeat
    我们已经快把所有基本的转换(Transformation)、过滤(Filter)和合并(Combination)的operators讲完了。今天要讲错误处理(ErrorHandling)的operators,错误处理是异步行为中的一大难题,尤其有多个交错的异步行为时,更容易凸显错误处理的困难。就让我们一起来看看在RxJS中能如何处理......
  • 30 天精通 RxJS (14):Observable Operator - throttle, debounce
    昨天讲到了在UI操作上很常用的delay,今天我们接着要来讲另外两个也非常实用operators,尤其在做性能优化时更是不可或缺的好工具!Operatorsdebounce跟buffer、bufferTime一样,Rx有debounce跟debounceTime一个是传入observable另一个则是传入毫秒,比较常用到的是de......
  • [转帖][译] 使用 Linux tracepoint、perf 和 eBPF 跟踪数据包 (2017)
    http://arthurchiao.art/blog/trace-packet-with-tracepoint-perf-ebpf-zh/ 译者序本文翻译自2017年的一篇英文博客 Tracingapacket’sjourneyusingLinuxtracepoints,perfandeBPF ,并添加了章节号以方便阅读。由于译者水平有限,本文不免存在遗漏或错误之处。如......
  • 降阶公式/ARC173F
    ARC173F题意给定\(n,A,B\),初始有一个集合\(S=\{1,2,\dots,A,A+1,A+2,\dots,A+B\}\)。进行如下操作\(n-1\)次使得剩下\(n\)个集合:从所有集合中选择一个,记为\(S_0\)。从\(S_0\)中选择一个元素\(a\)满足\(a\in[1,A]\),选择一个元素\(b\)满足\(b\in[A+1,A+B]\)。......
  • [题解] <NOIP2017> 时间复杂度
    [题解]NOIP2017时间复杂度题目描述小明正在学习一种新的编程语言A++,刚学会循环语句的他激动地写了好多程序并给出了他自己算出的时间复杂度,可他的编程老师实在不想一个一个检查小明的程序,于是你的机会来啦!下面请你编写程序来判断小明对他的每个程序给出的时间复杂度是否正......
  • 20212217刘恒谦-Exp4-恶意代码分析
    一、实践过程记录1、系统运行监控(1)使用如计划任务,每隔一分钟记录自己的电脑有哪些程序在联网,连接的外部IP是哪里。运行一段时间并分析该文件,综述一下分析结果。目标就是找出所有连网的程序,连了哪里,大约干了什么(不抓包的情况下只能猜),你觉得它这么干合适不。如果想进一步分析的,......