javascript - 在多个浏览器或设备上运行时计时器不同步

标签 javascript angular timer

我创建了一个在多个浏览器上不同步的计时器。在浏览器的非事件选项卡上,甚至在设备上,计时器运行得更快或更慢。 不同选项卡上有 3-4 秒的差异。如何同步它们?

这是我的模块代码:

import { Observable, BehaviorSubject, Subscription } from 'rxjs';
export class RAFTimer {
    public currentFrameId: number;
    public startTime: number;
    public numbers: BehaviorSubject<number>;
    constructor() {
        this._raf();
        this.numbers = new BehaviorSubject<number>(0);
        this.startTime = 0;
    }

    private _raf() {
        this.currentFrameId = requestAnimationFrame(timestamp => this._nextFrame(timestamp));
      }
      private _nextFrame(timestamp: number) {
        if ( this.startTime == 0) {
            this.startTime = timestamp;
        }
        const diff: number = timestamp - this.startTime;
        if ( diff > 100) {
           const n: number = Math.round(diff / 100);
          this.startTime = timestamp;
          this.numbers.next(n);
        }
        this._raf();
      }
      cancel() {
        cancelAnimationFrame(this.currentFrameId);
        this.currentFrameId = null;
      }
}

这是组件代码:

import { Component, Input, OnInit, OnDestroy } from '@angular/core';
import { RAFTimer } from './raftimer';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit{
  title = 'app';
  public timeInterval:number=10;
  public timeLeft:number=10000;
  constructor(private timer:RAFTimer) { 

  }

  ngOnInit() {
    let countNumber=1;
    let auctiontimer = this.timer.numbers.subscribe(
      (val) => {
          countNumber = countNumber+val;
          if(countNumber >= this.timeInterval) {
            this.timeLeft = this.timeLeft-countNumber/this.timeInterval;
            if(this.timeLeft<0) {
                this.timeLeft= 0;
            }
              countNumber=1;
          }
  }); 
  }

}

请在两个不同的选项卡上同时运行此网址,您将在几秒钟或 1 分钟内注意到差异。 https://angular-timer-raf.stackblitz.io/

如果您愿意,您还可以通过打开此网址来编辑这些代码行==>

网址 https://stackblitz.com/edit/angular-timer-raf

我还知道,当浏览器变得不活动时,计时器就会变慢,我搜索了很多东西,但没有一个对我有用。但无论如何我都需要同步计时器。

最佳答案

您创建了一个外部(我希望是全局的或特定于拍卖的)服务来获取剩余时间,并且您可以从该服务中获得可观察的结果。很好,我也会这样做!但我认为你应该从服务中删除“RequestAnimationFrame”。我的猜测是您正在使用它来更新 View 。你不应该那样做。 RequestAnimationFrame,就像“setTimeout()”一样,是一个依赖JS引擎在某个时间异步调用该方法的方法。在此之前,线程可能会被某些 View 层操作阻塞。

因此,您应该让 Angular 本身处理 View 更新,例如:<div>Time: {{timer.numbers | async}}</div> (异步管道会自动触发每个新值的更改检测)。

如果这没有帮助(不够精确),您可以考虑将计时器服务移动到完全不同的线程(浏览器中的 WebWorker)

您还可以利用后端每隔...秒同步一次您的 RAFTimer-Service。使用 REST,您可以通过每隔 ... 秒发出一次请求,询问当前时间和其他拍卖信息来实现这一点;我假设您正在制作拍卖/投标应用程序。使用 websockets,您可以通过让后端服务在每次更新/间隔时将该信息推送到客户端来实现这一点。

关于javascript - 在多个浏览器或设备上运行时计时器不同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50188074/

相关文章:

c# - 如何在C#中反序列化json对象

javascript - 脚本在 Chrome 中运行但不在 firefox 中运行

java - 使用条件 TimerTask 不会终止线程

javascript - clearInterval 按钮不停止 setInterval 倒计时

c - timer_settime 在 uClinux 上的 pthread 中调用处理函数

javascript - 如何在CKEditor中的<td>之后禁用自动</br>?

javascript - Chart JS - x 轴为天数的折线图

Angular 4 和 Materialise 的 CSS 封装

angular - 如何使用 golang 作为 API 服务器在 angular-4 中使用 JWT 获取用户的登录状态

git - Grunt/Git 在连接到 github.com 时抛出未知 SSL 协议(protocol)错误 :443