RxJs SwitchMapTo 操做符之移花接木

2021年09月15日 阅读数:5
这篇文章主要向大家介绍RxJs SwitchMapTo 操做符之移花接木,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

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

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

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

看个例子:spa

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));

输出:
code

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

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

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 时中止。rem

思路:触发计数器开始递减的操做是点击屏幕,所以须要使用 fromEvent 来构造 Observable :click$get

每隔两秒钟执行某项操做,所以须要用 interval 构造第二个 Observable.it

一旦计数器启动以后,每隔两秒钟须要执行递减操做,所以须要用 switchMapTo,将 click$ 映射成 interval Observable.

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

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

更多Jerry的原创文章,尽在:"汪子熙":