#angular #rxjs
#угловатый #rxjs #angular
Вопрос:
Я добавляю функцию секундомера в свой компонент таймера табло (изменив часы обратного отсчета, которые у меня были ранее). Секундомер работает непрерывно, но хотелось бы, чтобы секунды перестали увеличиваться через 20 секунд ( this.timePerQuestion
). Пожалуйста, не могли бы вы посмотреть мой код ниже и помочь мне с этой проблемой. Спасибо.
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)));
}
Ответ №1:
Вы можете сделать это несколькими способами: вы можете сделать stop$ a subject и выполнить эмиссию для него через 20 секунд. Самый простой способ — просто остановить таймер, как только он выдаст 20 значений. Ваш таймер запускается раз в секунду, поэтому, если вы возьмете (20), ваш таймер остановится через 20 секунд:
[....]
switchMapTo(
timer(0, 1000).pipe(
scan((acc) => acc 1, 0),
take(20) // <- Stops after 20 seconds
)
),
[....]
Ответ №2:
Рассмотрим ниже подход с использованием repeatWhen
operator. Смотрите демонстрацию на 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) {}
Комментарии:
1. Спасибо! Я постараюсь использовать оператор repeatWhen в своем коде и дам вам знать, если у меня возникнут какие-либо вопросы.
2. Похоже, мне нужно заменить Repeat when в моем коде в секундомере, не уверен, как должен выглядеть код. Я включил свой Stackblitz в свой пост выше.
3. Я только что просмотрел приложение. Похоже, ваш секундомер работает так, как ожидалось
4. Да, если вы переключитесь на таймер секундомера, вы увидите, что он работает, но мне нужно, чтобы он остановился на this.timePerQuestion, в противном случае часы работают непрерывно и не останавливаются.