辅助类操作符在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);
// 5
const 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
呢?