RxJs SwitchMapTo 操作符之移花接木

举报
汪子熙 发表于 2022/08/01 21:35:05 2022/08/01
【摘要】 将每个源值投影到同一个 Observable,该 Observable 在输出 Observable 中使用 switchMap 多次展平。输入一个 Observable,输出一个 function Operator. 实际是一个函数,每次在源 Observable 上发出值时,该函数都会返回一个 新的 Observable.该函数从给定的 innerObservable 发出项目,并且仅从...

将每个源值投影到同一个 Observable,该 Observable 在输出 Observable 中使用 switchMap 多次展平。

输入一个 Observable,输出一个 function Operator. 实际是一个函数,每次在源 Observable 上发出值时,该函数都会返回一个 新的 Observable.

该函数从给定的 innerObservable 发出项目,并且仅从最近投影的内部 Observable 中获取值。

看个例子:

import { EMPTY, range } from 'rxjs';
import { first, take, tap } from 'rxjs/operators';

import { fromEvent, interval } from 'rxjs';
import { switchMapTo } from 'rxjs/operators';

const clicks = fromEvent(document, 'click');

const test = event => console.log('Jerry: ', event);
const result = clicks.pipe(
  tap(test),

  switchMapTo(interval(1000))
);
result.subscribe(x => console.log(x));

输出:

每次点击之后,click$ 抛出的 PointerEvent,被 switchMapTo 返回的 Function Operator 丢弃了。最后用户订阅 result 函数里,打印的值,是 switchMapTo 输入的 interval(1000) Observable 发射的值,而不再是 clicks$ 抛出的 PointerEvent.

再看另一个在网页显示倒计时数字的例子。

import './style.css';

import { interval, fromEvent } from 'rxjs';
import {
  switchMapTo,
  scan,
  startWith,
  takeWhile,
  finalize
} from 'rxjs/operators';

const COUNTDOWN_TIME = 10;

// reference
const countdownElem = document.getElementById('countdown');

// streams
const click$ = fromEvent(document, 'click');
const countdown$ = interval(2000).pipe(
  scan((acc, _) => --acc, COUNTDOWN_TIME),
  startWith(COUNTDOWN_TIME)
);

click$
  .pipe(
    switchMapTo(countdown$),
    takeWhile(val => val >= -10),
    finalize(() => (countdownElem.innerHTML = "We're done here!"))
  )
  .subscribe((val: any) => (countdownElem.innerHTML = val));

初始整数是10,每隔2秒钟减一,减到 -10 时停止。

思路:触发计数器开始递减的操作是点击屏幕,因此需要使用 fromEvent 来构造 Observable :click$

每隔两秒钟执行某项操作,因此需要用 interval 构造第二个 Observable.

一旦计数器启动之后,每隔两秒钟需要执行递减操作,因此需要用 switchMapTo,将 click$ 映射成 interval Observable.

之后的值传递,就和 click$ 再无任何关联了。

因为是递减操作,暗示这是一个 stateful 场景,故选用 scan 操作符维护内部状态。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。