首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么我的RxJS倒计时不显示?

为什么我的RxJS倒计时不显示?
EN

Stack Overflow用户
提问于 2020-05-17 17:09:41
回答 2查看 683关注 0票数 0

我正在进行一个角形9测试应用程序,我使用RxJS作为倒计时计时器(在containers\scoreboard\time\time.component.ts中),而计时器似乎没有显示。stopTimer()函数应该在停止计时器的秒数上停止它。在正确的答案被选择之后,计时器应该停止,计时器应该在问题之间重置。每个问题经过的时间应该保存到elapsedTimes数组中。请在Stackblitz: TimeComponent上看到我的定时器代码:https://stackblitz.com/edit/angular-9-quiz-app。谢谢。

下面的代码是我第一次开始用RxJS构建一个倒计时时钟。我最近的代码是在Stackblitz上的。

代码语言:javascript
运行
复制
  countdownClock() {
    this.timer = interval(1000)
      .pipe(
        takeUntil(this.isPause),
        takeUntil(this.isStop)
      );
    this.timerObserver = {
      next: (_: number) => {
        this.timePerQuestion -= 1;
          ...
        }
    };

    this.timer.subscribe(this.timerObserver);
  }

  goOn() {
    this.timer.subscribe(this.timerObserver);
  }

  pauseTimer() {
    this.isPause.next();
    // setTimeout(() => this.goOn(), 1000)
  }

  stopTimer() {
    this.timePerQuestion = 0;
    this.isStop.next();
  }

我在我的stopTimer()中使用了stopTimer()和pauseTimer(),这样就可以从不同的组件调用它们。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-05-31 20:59:38

我已经修好了你的垃圾桶。基于对时间服务方法的调用,您的计时器将运行。

也不需要在拆卸逻辑中设置经过的时间。当计时器停止时,它会自动推送。

Stackblitz网址:- https://stackblitz.com/edit/angular-9-quiz-app-er3pjn

倒计时方法:-

代码语言:javascript
运行
复制
  countdownClock() {
    const $ = document.querySelector.bind(document);
    const start$ = this.timerService.isStart.asObservable().pipe(shareReplay(1));
    const reset$ = this.timerService.isReset.asObservable();
    const stop$ = this.timerService.isStop.asObservable();
    const markTimestamp$ = fromEvent($("#mark"), "click");
    const continueFromLastTimestamp$ = fromEvent($("#continue"), "click");
    start$.subscribe((data) => console.log(data));
    this.timeLeft$ = concat(start$.pipe(first()), reset$).pipe(
      switchMapTo(
        timer(0, 1000).pipe(
          scan((acc, crt) => acc > 0? acc - 1: acc, this.timePerQuestion),
        )
      ),
      takeUntil(stop$.pipe(skip(1))),
      repeatWhen(completeSbj =>
        completeSbj.pipe(
          switchMapTo(
            start$.pipe(
              skip(1),
              first()
            )
          )
        )
      )
    ).pipe(tap((value)=>this.timerService.setElapsed(this.timePerQuestion-value)));

在记分板组件参数订阅中,我已经重置了计时器,所以每当问题发生变化时,它都会重置。

票数 2
EN

Stack Overflow用户

发布于 2020-05-18 08:08:25

就像每一个复杂的问题一样,你必须把它分解成更小的、可消化的问题。

因此,我创建了一个StackBlitz演示,该演示重新创建了基本功能:

  • 启动计时器
  • 暂时停止(标记时间戳);例如,当选择所有答案时
  • 从上一个时间戳继续
  • 复位定时器
  • 停止定时器

以下是此代码:

代码语言:javascript
运行
复制
const $ = document.querySelector.bind(document);

const start$ = fromEvent($('#start'), 'click').pipe(shareReplay(1));
const reset$ = fromEvent($('#reset'), 'click');
const stop$ = fromEvent($('#stop'), 'click');
const markTimestamp$ = fromEvent($('#mark'), 'click');
const continueFromLastTimestamp$ = fromEvent($('#continue'), 'click');

const src$ = concat(
  start$.pipe(first()),
  reset$
).pipe(
  switchMapTo(
    timer(0, 1000)
      .pipe(
        takeUntil(markTimestamp$),
        repeatWhen(
          completeSbj => completeSbj.pipe(switchMapTo(
            continueFromLastTimestamp$.pipe(first())
          ))
        ),
        scan((acc, crt) => acc + 1000, 0)
      )
  ),
  takeUntil(stop$),
  repeatWhen(completeSbj => completeSbj.pipe(switchMapTo(start$.pipe(skip(1), first()))))
).subscribe(console.log)

让我们看看每一个相关的部分。

代码语言:javascript
运行
复制
concat(
  start$.pipe(first()),
  reset$
).pipe(switchMapTo(timer(...)))

只有当timer之前还没有启动(start$.pipe(first()))或者用户希望重置所有内容(reset$)时,它才会从0开始计数。

concat(a$, b$)确保b$不能发出,除非a$完成。

代码语言:javascript
运行
复制
timer(0, 1000)
  .pipe(
    takeUntil(markTimestamp$),
    repeatWhen(
      completeSbj => completeSbj.pipe(switchMapTo(
        continueFromLastTimestamp$.pipe(first())
      ))
    ),
    scan((acc, crt) => acc + 1000, 0)
  )

我们希望计时器处于活动状态,直到markTimestamp$发出。当发生这种情况时,源(timer(0, 1000))将被取消订阅。使用repeatWhen,我们可以决定何时重新订阅timer。也就是说,当continueFromLastTimestamp$.pipe(first())发射的时候。重要的是我们使用first(),否则源可能会被多次重新订阅。

scan((acc, crt) => acc + 1000, 0)放在repeatWhen之后确保最后一个时间戳不会丢失。例如,计时器可能从X开始,在X+5,用户触发markTimestamp$,然后在X + 100,用户触发continueFromLastTimestamp$。发生这种情况时,定时器将发出X+6

代码语言:javascript
运行
复制
takeUntil(stop$),
repeatWhen(completeSbj => completeSbj.pipe(switchMapTo(start$.pipe(skip(1), first()))))

计时器应该处于活动状态,直到stop$发出。然后,只有当用户再次触发start$时,它才能重新启动。之所以使用skip(1),是因为我们不使用start$shareReplay使用的ReplaySubject所缓存的值,而使用first()是因为只应该是一次。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61855688

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档