RxJS 条件/布林类型 Operators (1) - isEmpty / defaultIfEmpty / find / finxIndex / every

今天介绍「条件/布林类型」的 operators,这类型的 operators 都是用来判断整个 Observable 是否符合某些条件来当作新的 Observable 事件资料。

isEmpty

isEmpty 会判断来源 Observable 是否没有「发生过任何事件值」,如果到结束时完全没有任何事件发生过,则会发生 true 事件在新的 Observable 上,反之则新的 Observable 会发生 false 事件。

EMPTY
  .pipe(isEmpty())
  .subscribe(data => {
    console.log(`isEmpty 示范 (1): ${data}`)
  });
// isEmpty 示范 (1): true

const emptySource$ = new Subject();
emptySource$
  .pipe(isEmpty())
  .subscribe(data => {
    console.log(`isEmpty 示范 (2): ${data}`)
  });
setTimeout(() => emptySource$.complete(), 2000);
// isEmpty 示范 (2): true

上面程序中,我们建立两种 Observable,一种是使用 EMPTY 直接建立一个空的 Observable,第二种是使用 Subject 建立 Observable,但没有让任何事件发生,并在两秒後结束;由於两种 Observable 过程中都没有任合新的事件发生,因此最终会得到 true 的结果。

弹珠图:

-----------|
isEmpty()
-----------(true|)

如果过程中有发生过事件呢?当然就会得到 false 的结果:

interval(1000)
  .pipe(
    take(3),
    isEmpty()
  )
  .subscribe(data => {
    console.log(`isEmpty 示范 (3): ${data}`)
  });
// isEmpty 示范 (3): false

由於有事件发生,确定不是空的 Observable,因此在事件发生同时,就会得到 false 同时结束 Observable。

弹珠图:

---0---1---2---3---4---5...
take(3)
---0---1---2|
isEmpty()
---(false|)

程序码:https://stackblitz.com/edit/mastering-rxjs-operator-isempty

defaultIfEmpty

defaultIfEmpty 会在 Observable 没有任何事件发生就结束时,给予一个预设值:

const emptySource$ = new Subject();
emptySource$
  .pipe(defaultIfEmpty('a'))
  .subscribe(data => {
    console.log(`defaultIfEmpty 示范 (1): ${data}`)
  });
setTimeout(() => emptySource$.complete(), 2000);
// defaultIfEmpty 示范 (1): a

上面程序中,由於来源 Observable 是一个空的 Observable,因此会给予一个指定的预设值。

弹珠图:

------|
defaultIfEmpty('a')
------(a|)

如果过程中有发生事件值呢?那麽当然 defaultIfEmpty 就不做任何事情罗:

interval(1000)
  .pipe(
    take(3),
    defaultIfEmpty(-1) // 因为来源 Observable 有事件值,因此不做任何事情
  )
  .subscribe(data => {
    console.log(`defaultIfEmpty 示范 (2): ${data}`);
  });
// defaultIfEmpty 示范 (2): 0
// defaultIfEmpty 示范 (2): 1
// defaultIfEmpty 示范 (2): 2

程序码:https://stackblitz.com/edit/mastering-rxjs-operator-defaultifempty

find

find 内需要传入一个 predictate callback function,find 会将事件资讯传入此 function,并回传是否符合指定的条件,如果符合,就会将目前的事件资料发生在新的 Observable 上,同时完成 Observable。

interval(1000)
  .pipe(find(data => data === 3))
  .subscribe(data => {
    console.log(`find 示范: ${data}`);
  });
// find 示范: 3

上述程序的来源是一个每秒发生一次且不会结束的 Observable,透过 find,当符合资料等於 3 时,就使用这个资料作为新的 Observable 事件资料,同时结束整个 Observable。

弹珠图:

---0---1---2---3---4---5.....
find(data => data === 3)
---------------(3|)

程序码:https://stackblitz.com/edit/mastering-rxjs-operator-find

findIndex

findIndexfind 一样需要一个 predicate callback function,差别在於 findIndex 的条件符合时,新的 Observable 事件资料是「符合条件事件的索引值」,也就是这个事件是来源 Observable 的第几次事件:

interval(1000)
  .pipe(
    map(data => data * 2),
    findIndex(data => data === 6)
  )
  .subscribe(data => {
    console.log(`findIndex 示范: ${data}`);
  });
// findIndex 示范: 3

上面程序中,符合条件的资料为 6 因此将它发生在来源 Observable 的索引值 3 发生在新的 Observable 上,同时结束。

弹珠图:

---0---1---2---3---4-...
map(data => daya * 3)
---0---2---4---6---8-...
findIndex(data => data === 6)
---------------(3|)
                ^ 来源资料的索引值

程序码:https://stackblitz.com/edit/mastering-rxjs-operator-findindex

every

every 也是传入一个 predicate callback function,every 会将事件资讯传入此 function,并判断来源 Observable 是否「全部符合指定条件」,如果符合,在来源 Observable 结束时会得到 true 事件;如果不符合,则会在事件资料不符合指定条件同时得到 false 事件并结束。

const source$ = interval(1000)
  .pipe(
    map(data => data * 2),
    take(3)
  );

source$
  .pipe(
    every(data => data % 2 === 0)
  )
  .subscribe(data => {
    console.log(`every 示范 (1): ${data}`);
  });
// every 示范 (1): true

上面程序的 source$ 资料都会是 2 的倍数,符合 every 内条件,因此在 Observable 结束时,会得到 true 事件。

弹珠图:

---0---2---4|
every(data => data % 2 === 0)
-----------(true|)

当有事件值不符合时,会立刻收到此事件并结束。

interval(1000)
  .pipe(every(data => data % 2 === 0))
  .subscribe(data => {
    console.log(`every 示范 (2): ${data}`);
  });
// every 示范 (2): false

弹珠图:

---0---1---2---3....
every(data => data % 2 === 0)
-------(false|)

程序码:https://stackblitz.com/edit/mastering-rxjs-operator-every

本日小结

  • isEmpty:用来判断来源 Observable 是否是空的,也就是没有任何事件发生就结束了。
  • defaultIfEmpty:当来源 Observable 是空的时候,给予一个预设值。
  • find:用来判断来源 Observable 是否有符合条件的事件资料,如果有,将此事件资料发生在新的 Observable 上,并结束。
  • findIndex:用来判断来源 Observable 是否有符合条件的事件资料,如果有,将此事件资料在来源 Observable 的索引值发生在新的 Observable 上,并结束。
  • every:用来判断来源 Observable 的事件是否「全部符合指定条件」。

相关资源


<<:  mostly:functional 第二十六章的试炼:Functor 的证明

>>:  【这些年我似是非懂的 Javascript】Day 27 - 物件 # Part 3 # 特性描述器

[Day 10] SRE - ON-CALL

ON-CALL 今天为大家介绍ON-CALL常见的须注意之事项 建立心态 我为人人,人人为我,今天你...

Day3 中秋就是要烤肉阿-美式烤猪肋排

中秋就是要烤肉阿 虽然今年因为疫情无法在外群聚烤肉,但仪式感不能少,自己在家烤起来! 这次来点不一样...

Progressive Web App 透过系统分享内容: Web Share API & Web Share Target (17)

什麽是 Web Share API Web App 透过 Web Share API 就能够使用系统...

【Day24】Git 版本控制 - 修改 commit 纪录:amend

上一次有提到说,修改 commit 的方式有以下几种: 把 .git 目录整个删除,暴力破解法,请不...

#9 Web Crawler 2

We are going to start coding!! 想法 这个爬虫的想法很简单,对於每个 ...