Angular 选项卡更改时的Rxjs间隔变慢

Angular 选项卡更改时的Rxjs间隔变慢,angular,firebase,rxjs,Angular,Firebase,Rxjs,我正在开发firebase在线考试应用程序。在游戏中,我有10秒后完成的进度条,用户应该完成答案。我使用了这个间隔函数来设置10秒的动画 .ts .html 但是我注意到,当选项卡不活动时,进度条非常不稳定或非常慢。我不希望用户打开“切换”选项卡并查找答案,然后返回应用程序并继续。如何处理这种情况?间隔和超时不准确。它们只允许被授权人在指定时间后调用方法。根据这一点,当tab处于非活动状态时,进度可能会变慢。我建议使用时间戳 startGame() { const gameStartTime

我正在开发firebase在线考试应用程序。在游戏中,我有10秒后完成的进度条,用户应该完成答案。我使用了这个间隔函数来设置10秒的动画

.ts

.html


但是我注意到,当选项卡不活动时,进度条非常不稳定或非常慢。我不希望用户打开“切换”选项卡并查找答案,然后返回应用程序并继续。如何处理这种情况?

间隔和超时不准确。它们只允许被授权人在指定时间后调用方法。根据这一点,当tab处于非活动状态时,进度可能会变慢。我建议使用时间戳

startGame() {
  const gameStartTimestamp = Date.now();
  const gameEndTimestamp = gameStartTimestamp + 10000

  interval(100)
    .pipe(
      map(() => Date.now()),
      takeWhile(date => date < gameEndTimestamp)
    )
    .subscribe(date => {
      this.progressTimer = Math.round((now - this.gameStartTimestamp) / 100)
    })
);

我还用了Poul的演示,并在那里应用了我的更改

间隔和超时不准确。它们只允许被授权人在指定时间后调用方法。根据这一点,当tab处于非活动状态时,进度可能会变慢。我建议使用时间戳

startGame() {
  const gameStartTimestamp = Date.now();
  const gameEndTimestamp = gameStartTimestamp + 10000

  interval(100)
    .pipe(
      map(() => Date.now()),
      takeWhile(date => date < gameEndTimestamp)
    )
    .subscribe(date => {
      this.progressTimer = Math.round((now - this.gameStartTimestamp) / 100)
    })
);
我还提供了Poul的演示,并在那里应用了我的更改

如果你检查你看到chrome的后台选项卡的最小计时器间隔为1000毫秒,这意味着你的10毫秒回调不会被触发。可以将间隔增加到1000ms,并覆盖动画以使其平滑:

ts:

模板:

<mat-progress-bar mode="determinate" [value]="progress$ | async"></mat-progress-bar>
如果你想要的是准确度,Date.now也不会提供,因为在回答过程中很容易通过更改系统时间来伪造

如果您使用的是firebase,那么如果您使用的是firestore数据库,则可以使用该方法获取当前服务器的时间戳。然而,这很可能会有一个短暂的网络延迟,如果您检查chrome后台选项卡的最小计时器间隔为1000毫秒,那么您的代码显然会有点不同,这意味着您的10毫秒回调不会被触发。可以将间隔增加到1000ms,并覆盖动画以使其平滑:

ts:

模板:

<mat-progress-bar mode="determinate" [value]="progress$ | async"></mat-progress-bar>
如果你想要的是准确度,Date.now也不会提供,因为在回答过程中很容易通过更改系统时间来伪造


如果您使用的是firebase,那么如果您使用的是firestore数据库,则可以使用该方法获取当前服务器的时间戳。然而,这很可能会有一个短暂的网络延迟,您的代码显然会有点不同

您可以将您的函数更改为此函数吗。 如果你能用简单的方法来做,就不要用困难的方法来做

timer;
startGame() {
  this.timer = setInterval(() => {
     this.progressTimer = this.progressTimer + 10;
     if (this.progressTimer >= 100) {
       clearInterval(this.timer);
     }
  }, 1000);
}

你能把你的函数改成这个函数吗。 如果你能用简单的方法来做,就不要用困难的方法来做

timer;
startGame() {
  this.timer = setInterval(() => {
     this.progressTimer = this.progressTimer + 10;
     if (this.progressTimer >= 100) {
       clearInterval(this.timer);
     }
  }, 1000);
}

你的解决方案看起来不错。我不关心精确性。但为什么当我换了账单回来。进度条先向后再向前。您的解决方案看起来不错。我不关心精确性。但为什么当我换了账单回来。进度条是先退后进。为什么我换了标签又回来了。进度条先向后,然后向前。但解决方案看起来不错当进度条加载时,更改选项卡,等待4秒,然后返回。在你的应用程序中,而不是在stackblitz中,可以看到进度的行为。我猜当我更改选项卡并返回时,为什么它对我有效。进度条先向后,然后向前。但解决方案看起来不错当进度条加载时,更改选项卡,等待4秒,然后返回。在应用程序中查看进度的行为,而不是在stackblitz中,我想它对我有用
timer;
startGame() {
  this.timer = setInterval(() => {
     this.progressTimer = this.progressTimer + 10;
     if (this.progressTimer >= 100) {
       clearInterval(this.timer);
     }
  }, 1000);
}