0
votes

I'm adding a stopwatch feature to my scoreboard timer component (by modifying the countdown clock I had previously). The stopwatch runs continuously, but would like it so that the seconds stop incrementing after 20 seconds (this.timePerQuestion). Please could you see my code below and help me with this issue. Thank you.

  stopwatch(): void {
    this.start$ = this.timerService.start$;
    this.reset$ = this.timerService.reset$;
    this.stop$ = this.timerService.stop$;

    this.time$ = concat(this.start$.pipe(first())).pipe(
      switchMapTo(
        timer(0, 1000).pipe(
          scan((acc) => acc + 1, 0)
        )
      ),
      takeUntil(this.stop$.pipe(skip(1))),
      repeatWhen(completeSubj =>
        completeSubj.pipe(
          switchMapTo(
            this.start$.pipe(
              skip(1),
              first()
            )
          )
        )
      )
    ).pipe(tap((value: number) => this.timerService.setElapsed(value)));
  }
2

2 Answers

3
votes

There are a few ways you can do this: You can make stop$ a subject and emit on it after 20 seconds. The easiest way though is to just stop your timer once it's emitted 20 values. Your timer emits once every second, so if you take(20), your timer will stop after 20 seconds:

[....]
switchMapTo(
  timer(0, 1000).pipe(
    scan((acc) => acc + 1, 0),
    take(20) // <- Stops after 20 seconds
  )
),
[....]
0
votes

Consider below approach using repeatWhen operator. See Demo On Stackblitz

timer-service.ts

  stop$ = new Subject();
  start$ = new Subject();
  questionStarted$ = new BehaviorSubject(true);
  questionLength = 5000; // Change to 20000
  questionLengthSubject$ = new BehaviorSubject(this.questionLength);
  questionLength$ = this.questionLengthSubject$.asObservable();

  stopTimer = () => {
    this.stop$.next();
    this.questionStarted$.next(false);
  };
  startTimer = () => {
    this.start$.next();
    this.questionStarted$.next(true);
  };
  setQuestionLength = questionLength =>
    this.questionLengthSubject$.next(questionLength);

  timer$ = timer(0, 1000).pipe(
    takeUntil(this.stop$),
    repeatWhen(() => this.start$)
  );

  tick$ = combineLatest([this.timer$, this.questionLength$]).pipe(
    tap(([timer, questionLength]) => {
      if (questionLength <= timer * 1000) {
        this.stopTimer();
      }
    }),
    map(([timer, questionLength]) => questionLength / 1000 - timer)
  );

app.component.ts

  tick$ = this.timerService.tick$;
  questionStarted$ = this.timerService.questionStarted$;
  startTimer = this.timerService.startTimer;
  stopTimer = this.timerService.stopTimer
  constructor (private timerService: TimerService) {}