[RxJS] Refactoring Composable Streams in RxJS, switchMap()

Refactoring streams in RxJS is mostly moving pieces of smaller streams around. This lessons demonstrates a simple refactoring by requiring the StopWatch to be more configurable.

 

 Code we have now:
const Observable = Rx.Observable;

const startButton = document.querySelector('#start');
const stopButton = document.querySelector('#stop');
const resetButton = document.querySelector('#reset');

const start$ = Observable.fromEvent(startButton, 'click');
const interval$ = Observable.interval(1000);
const stop$ = Observable.fromEvent(stopButton, 'click');
const reset$ = Observable.fromEvent(resetButton, 'click');


const data = {count:0};
const inc = (acc)=> ({count: acc.count + 1});
const reset = (acc)=> data;

const intervalThatStops$ = interval$
    .takeUntil(stop$);

const incOrReset$ = Observable.merge(
    intervalThatStops$.mapTo(inc),
    reset$.mapTo(reset)
);

start$
    .switchMapTo(incOrReset$)
    .startWith(data)
    .scan((acc, curr)=> curr(acc))
    .subscribe((x)=> console.log(x));

 

Currently the interval is hard code 1000, we want it more flexable:

const Observable = Rx.Observable;

const startButton = document.querySelector('#start');
const halfButton = document.querySelector('#half');
const quarterButton = document.querySelector('#quarter');

const stopButton = document.querySelector('#stop');
const resetButton = document.querySelector('#reset');

const start$ = Observable.fromEvent(startButton, 'click');
const half$ = Observable.fromEvent(halfButton, 'click');
const quarter$ = Observable.fromEvent(quarterButton, 'click');

const stop$ = Observable.fromEvent(stopButton, 'click');
const reset$ = Observable.fromEvent(resetButton, 'click');

We added two more buttons, halfButton set interval as 500, and quarterButton is 250.

 

So when we click "start", "half" or "quarter" button, the interval will set differently.

 Observable.merge(
    start$.mapTo(1000),
    half$.mapTo(500),
    quarter$.mapTo(250)
 )

We want pass the time (1000, 500, 250) to the next observable to control the time.

 Observable.merge(
    start$.mapTo(1000),
    half$.mapTo(500),
    quarter$.mapTo(250)
 )
  .switchMap(
    (time) => {
      return Observable.merge(
        Observable.interval(time)
        .takeUntil(stop$)
        .mapTo(inc),
        reset$.mapTo(reset)
      )
    }
  )

We use switchMap() instead of switchMapTo() is becuase switchMapTo() accept observable as param and switchMap accpet a function which return an Observable. So use switchMap() is more flexable.

-------------

const Observable = Rx.Observable;

const startButton = document.querySelector('#start');
const halfButton = document.querySelector('#half');
const quarterButton = document.querySelector('#quarter');

const stopButton = document.querySelector('#stop');
const resetButton = document.querySelector('#reset');

const start$ = Observable.fromEvent(startButton, 'click');
const half$ = Observable.fromEvent(halfButton, 'click');
const quarter$ = Observable.fromEvent(quarterButton, 'click');

const stop$ = Observable.fromEvent(stopButton, 'click');
const reset$ = Observable.fromEvent(resetButton, 'click');


const data = {count:0};
const inc = (acc)=> ({count: acc.count + 1});
const reset = (acc)=> data;

 Observable.merge(
    start$.mapTo(1000),
    half$.mapTo(500),
    quarter$.mapTo(250)
 )
  .switchMap(
    (time) => {
      return Observable.merge(
        Observable.interval(time)
        .takeUntil(stop$)
        .mapTo(inc),
        reset$.mapTo(reset)
      )
    }
  )
 .startWith(data)
 .scan( (acc, curr) => curr(acc))
 .subscribe( (z) => console.log(z) );

 

 

posted @ 2016-03-11 03:34  Zhentiw  阅读(796)  评论(0编辑  收藏  举报