Home > Net >  Countdown timer with rxjs
Countdown timer with rxjs

Time:03-02

I need to start the timer by clicking the button. But this is not happening

public startTimerRxjs() {

  this.timeLeft$ = timer(0, 1000).pipe(
    takeWhile(() => this.timeLeft > 0),
    map(() => {
      this.timeLeft--;
      this.changeDetRef.detectChanges();
      return this.timeLeft;
    })
  );
}

CodePudding user response:

You can use a variable that counts down your emits. In rxjs variables (state) is processed by the scan operator. With the takeWhile you can stop your stream emitting.

const { timer } = rxjs;
const { scan, takeWhile, asyncScheduler } = rxjs.operators

const result$ = timer(0, 1000).pipe(
  scan(ticks => --ticks, 5),
  takeWhile(v => v >= 0)
);

result$.subscribe(console.log)
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/7.4.0/rxjs.umd.min.js"></script>

To reuse it and with more comments I created a custom operator called countdown that wraps your problem.

const { timer } = rxjs;
const { scan, takeWhile, asyncScheduler } = rxjs.operators

/*
* dueTime, intervalOrScheduler, schedule: timer api - https://rxjs.dev/api/index/function/timer
* maxTicks: describe the max timer emits
*/
const countdown = (dueTime = 0, intervalOrScheduler, maxTicks = 0, scheduler = asyncScheduler) => timer(dueTime, intervalOrScheduler).pipe(
  // start with the maxTicks value and decrease every emit
  scan(remainingTicks => --remainingTicks, maxTicks),
  // stop emitting when maxTicks reaches -1
  takeWhile(v => v >= 0)
);

const result$ = countdown(0, 1000, 5)

result$.subscribe(console.log)
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/7.4.0/rxjs.umd.min.js"></script>

CodePudding user response:

Either use the async pipe in your component (without using a button to trigger it), or subscribe in code:

<div>{{ timeLeft | async }}</div>

or:

this.timeLeft$ = timer(0, 1000)
  .pipe(
    takeWhile(() => this.timeLeft > 0),
    map(() => {
      this.timeLeft--;
      this.changeDetRef.detectChanges();
      return this.timeLeft;
    })
  ).subscribe();
  • Related