辅助类操作符在RxJS
中是比较特殊的操作符
数学类操作符
数学类操作符在RxJS
中只有4个,分别是
count
max
min
reduce
它们的特点是,会遍历上游Observable
对象中吐出的所有数据,换句话说,就是当上游数据完结时,才会给下游传递数据
count
count
操作符的作用是计算上游吐出的数据个数
import { range } from "rxjs";import { count } from "rxjs/operators";const source$ = range(1, 20).pipe(count());source$.subscribe(console.log);// 20
如果上游不是立刻完结的
const source$ = interval(500).pipe( take(10), count());source$.subscribe(console.log);// 等待5秒后// 10
由于数学类操作符会等待上游完结,所以等待5秒后,上游吐出数据,才会计算count
min和max
min
和max
操作符的用法是相同的,所以仅以max
操作符举例
import { of } from "rxjs";import { max } from "rxjs/operators";const source$ = of(1, 3, 5, 4, 2).pipe(max());source$.subscribe(console.log);// 5const sourceStr$ = of("ha", "ah", "xi", "zh", "zn").pipe(max());sourceStr$.subscribe(console.log);// "zn"
max
操作符对于数字以数字大小比较,对于字符串使用ASICII
码比较
除了默认的比较方式,还可以接收自定义的comparer
函数来比较复杂值
const source$ = of({ value: 2 }, { value: 1 }, { value: 3 }).pipe( min((x, y) => x.value - y.value));source$.subscribe(console.log);// { value: 1}
reduce
reduce
操作符和javascipt
原生的reduce
函数是一样的,只不过吐出的结果是Observable
对象
import { range } from "rxjs";import { reduce } from "rxjs/operators";const source$ = range(1, 100).pipe(reduce((acc, value) => acc + value, 0));source$.subscribe(console.log);
reduce
接收两个参数,第一个参数是规约函数,第二个参数是种子值
规约函数接收两个参数,第一个参数是上次累积的值,第二个参数是当前的值,函数需要返回一个当前累积值给下一次计算使用
种子值也就是初始值,是可选的,默认会使用数据集合中的第一个值作为初始值,这样会跳过第一个值的计算,将第一个值作为acc
参数传给第二次累积计算
reduce计算平均值
import { range } from "rxjs";import { map, reduce } from "rxjs/operators";const source$ = range(1, 100).pipe( reduce( (acc, value) => ({ sum: acc.sum + value, count: ++acc.count }), { sum: 0, count: 0 } ), map(value => value.sum / value.count));source$.subscribe(console.log);// 50.5
条件布尔类操作符
条件布尔类操作符会根据上游Observable
对象的数据和判定条件产生一个新的Observable
对象,
在RxJS
中有5种布尔类操作符
every
find
findIndex
isEmpty
defaultEmpty
其中every
、find
、findIndex
操作符都接受一个函数参数
这个函数被称为判定函数,判定函数就是判定输入是否满足某个条件
判定函数又接收3个参数,第一个参数是当前的值,第二个参数是索引,第三个值是Observable
数据源
every
every
操作符和数组中的every
相似,如果数据集合中的每一个值的判定结果都是true
,every
操作符就会吐出true
,如果有一个值不满足条件,那every
操作符会立即吐出false
并且不会对之后的值进行验证
import { range } from "rxjs";import { every } from "rxjs/operators";const source$ = range(1, 10).pipe(every(value => value > 1));source$.subscribe(console.log);// false
因为第一个数据1
不满足条件,所以会立刻吐出false
find和findIndex
find
和findIndex
操作符功能也和数组的方法相同,不同的是
- 如果数据集合中的某一个值通过验证函数,
find
返回的是通过的值,findIndex
是返回的当前的值的索引 - 如果数据集合中没有一个值能通过验证,
find
会返回undefined
,而findIndex
会返回-1
import { of } from "rxjs";import { find, findIndex } from "rxjs/operators";const sourceFind$ = of({ value: 1 }, { value: 2 }, { value: 3 }).pipe( find(item => item.value === 2));sourceFind$.subscribe(console.log);// { value: 2 }const sourceFindIndex$ = of({ value: 1 }, { value: 2 }, { value: 3 }).pipe( findIndex(item => item.value === 5));sourceFindIndex$.subscribe(console.log);// -1
isEmpty
isEmpty
操作符的作用就如其名,判定上游的Observable
对象是否没有吐出数据就直接complete
了
import { EMPTY } from "rxjs";import { isEmpty } from "rxjs/operators";const source$ = EMPTY.pipe(isEmpty());source$.subscribe(console.log);// true
defaultEmpty
defaultEmpty
操作符接收一个可选参数,这个参数是上游为empty
时吐出的默认值
defaultEmpty
操作符和isEmpty
相同的地方在它们都会在上游Observable
对象为空的时候吐出数据,不同的是isEmpty
吐出的是布尔值,而defaultEmpty
会吐出一个默认值
import { EMPTY } from "rxjs";import { defaultIfEmpty } from "rxjs/operators";const source$ = EMPTY.pipe(defaultIfEmpty("empty"));source$.subscribe(console.log);// empty
需要注意的一点是,如果没有给defaultEmpty
传参,它会吐出一个null
而不是undefined
话说有一个疑问,既然有every
操作符,为什么没有some
呢?