rxjsobservable

How to add a stop and start feature for an RxJS timer?


I added a start, stop, pause button. Start will start a count down timer which will start from a value, keep decrementing until value reaches 0. We can pause the timer on clicking the pause button. On click of Stop also timer observable completes.

const subscription = merge(
  startClick$.pipe(mapTo(true)),
  pauseBtn$.pipe(mapTo(false))
)
  .pipe(
    tap(val => {
      console.log(val);
    }),
    switchMap(val => (val ? interval(10).pipe(takeUntil(stopClick$)) : EMPTY)),
    mapTo(-1),
    scan((acc: number, curr: number) => acc + curr, startValue),
    takeWhile(val => val >= 0),
    repeatWhen(() => startClick$),
    startWith(startValue)
  )
  .subscribe(val => {
    counterDisplayHeader.innerHTML = val.toString();
  });

Stackblitz Code link is available here


Solution

  • This is a pretty complicated usecase. There are two issues I think:

    So to avoid all that I think you can just complete the chain using takeUntil(stopClick$) and then immediatelly resubscribe with repeat() to start over.

    merge(
      startClick$.pipe(mapTo(true)),
      pauseBtn$.pipe(mapTo(false))
    )
      .pipe(
        switchMap(val => (val ? interval(10) : EMPTY)),
        mapTo(-1),
        scan((acc: number, curr: number) => acc + curr, startValue),
        takeWhile(val => val >= 0),
        startWith(startValue),
        takeUntil(stopClick$),
        repeat(),
      )
      .subscribe(val => {
        counterDisplayHeader.innerHTML = val.toString();
      });
    

    Your updated demo: https://stackblitz.com/edit/rxjs-tum4xq?file=index.ts