如何在javascript中管理多个计时器

How to manage multiple timers in javascript?

本文关键字:计时器 管理 javascript      更新时间:2023-09-26

下面是我使用的一个计时器的编码:

var sec = 0;
function pad ( val ) { return val > 9 ? val : "0" + val; }       
function setTime()
{
    document.getElementById("seconds0").innerHTML=pad(++sec%60);
    document.getElementById("minutes0").innerHTML=pad(parseInt(sec/60,10));
}
var timer = setInterval(setTime, 1000);

如果我有两个计时器,我这样写:

var sec = 0;
var sec1 = 0;
function pad ( val ) { return val > 9 ? val : "0" + val; }       
function setTime()
{
    document.getElementById("seconds0").innerHTML=pad(++sec%60);
    document.getElementById("minutes0").innerHTML=pad(parseInt(sec/60,10));
}
function setTime1()
{
    document.getElementById("seconds1").innerHTML=pad(++sec1%60);
    document.getElementById("minutes1").innerHTML=pad(parseInt(sec1/60,10));
}
var timer = setInterval(setTime, 1000);
var timer1 = setInterval(setTime1, 1000);

其实我用的计时器是用来显示人们等待的时间。人数是一个未知变量。也就是说它可以从1到100。所以,一个人是一个计时器。下面是我写的函数。

showWait = function(){
    var html = "";
    for (var i = 0; i < total; i++) 
    {                 
            html += '<div id="numbers" class="col-sm-3 col-xs-6">'+i+'</div>';
            html += '<div id="qtime" class="col-sm-3 col-xs-6"></span><div><span class="glyphicon glyphicon-time"></span> Waiting</div><div id="waittime"><label id="minutes'+i+'">00</label>:<label id="seconds'+i+'">00</label></div></div>';
            html += '</div>';
    }
$('#waitnumber').html(html);
}

所以,我不认为创建更多定时器的方法是一遍又一遍地重复相同的函数,对吧?如果有100个人,就不可能有100个计时器,对吧?有没有更简单的方法来管理多个计时器?

我猜每个间隔都有1000毫秒的等待时间,所以你不需要多个计时器,只需要一个,在这个计时器中做你需要的每个人

var sec = [time0, time1, time2 ....];
function pad ( val ) { return val > 9 ? val : "0" + val; }       
function setTime()
{
    for(person = 0; person < numberOfPeople; person++)
    {
        document.getElementById("seconds" + person).innerHTML=pad(++sec[person]%60);
        document.getElementById("minutes" + person).innerHTML=pad(parseInt(sec[person]/60,10));
    }
}
var timer = setInterval(setTime, 1000);

如果每个人的时间间隔是固定的,那么我建议你应该只运行一个1000ms的计时器,并为每个人定义某些变量,即像这样的

var persons = [
    {id : 0, min : 0, sec : 0, othercounts: 0},
    {id : 1, min : 0, sec : 0, othercounts: 0}
]

和定时器函数的执行,只是通过迭代数组或(任何你觉得舒服的数据结构),并增加每个人的时间计数器变量和刷新dom。

你的定时器功能将是这样的:

function setTime(){
    persons.forEach(function(p){
    p.min ++; 
    // your logic
    document.getElementById("seconds"+ e.id).innerHTML=pad(++sec%60);
    document.getElementById("minutes" + e.id).innerHTML=pad(parseInt(sec/60,10));
    });
}

并只注册一次间隔,即在文档加载事件或自定义事件

var timer = setInterval(setTime, 1000);

在新人员到达时,只需将person对象推入persons数组。

这只是一种方法,在循环结束时只呈现一次html可以有更好的解决方案。

我一直在研究同样的问题。我想到了一个解决方案,但我想看看互联网是否有更好的解决方案。我的解决方案是创建一个单例类来管理计时器,创建另一个计时器类来存储有关特定计时器实例的信息。下面是我实现的一个低级示例。

单例TimerManager类

// singleton class to manage timers.
class TimerManager {
  #timers;
  constructor() {
    if (TimerManager.instance === null) {
      TimerManager.instance = this
      this.#timers = [];
      this.tickInterval = null;
      this.active = false;
    } else {
      return TimerManager.instance;
    }
  }
  #stopAllTimers() {
    this.#timers.forEach((timer) => {
      if (timer.isRunning) {
        timer.isRunning = false;
      }
    });
  }
  start() {
    if (!this.active) {
      console.log("Starting the TimeManager");
      this.active = true;
      this.tickInterval = setInterval(
        (self) => {
          self.#timers.forEach((timer) => {
            if (timer.isRunning) {
              timer.seconds--;
              console.log({
                id: timer.timerId,
                sec: timer.seconds,
              });
            }
          });
        },
        1000,
        this
      );
    }
  }
  stop() {
    if (this.active) {
      this.active = false;
      clearInterval(this.tickInterval);
      this.#stopAllTimers();
      console.log("TimeManager has stopped");
    }
  }
  // crud operations
  // create
  addTimer(timer) {
    if (timer instanceof Timer) {
      console.log(`adding timer: ${timer.timerId}`);
      this.#timers.push(timer);
    } else {
      console.warn(
        "The argument passed into addTimer must be an instance of Timer"
      );
    }
    return this;
  }
  // read
  getTimerById(timerId) {
    const res = this.#timers.filter((timer) => timer.timerId === timerId);
    if (res.length === 1) {
      return res[0];
    } else {
      console.warn(`could not find timer with the id of ${timerId}`);
      return null;
    }
  }
  // update
  updateTimerById(timerId, updates) {
    this.getTimerById(timerId).update(updates);
  }
  // delete
  removeTimerById(id) {
    console.log(`Removing timer: ${id}`);
    this.#timers = this.#timers.filter((timer) => id !== timer.timerId);
    console.log(this.#timers);
  }
}
TimerManager.instance = null;

这里选择使用单例类是为了让所有计时器都可以用一个setInterval来更新,这个setInterval存储在tickInterval属性中。作为一个单例类,该类只有一个实例。话虽如此,我把各个计时器的所有逻辑都留给了Timer类,我将在接下来向您展示这个类。TimeManager.getTimerById()允许我们从列表中访问计时器并调用任何Timer方法。我还使用了一个静态属性numTimers来跟踪和自动增加新计时器的timerId,因为它们是创建的。

class Timer {
  static numTimers = 0;
  constructor(seconds = 30) {
    Timer.numTimers++;
    this.timerId = `timer${Timer.numTimers}`;
    this.isRunning = false;
    this.initialSeconds = seconds;
    this.seconds = seconds;
  }
  tick() {
    if (this.isRunning) {
      this.seconds--;
    }
  }
  activateTimer() {
    console.log(`Starting timer: ${this.timerId}`);
    this.isRunning = true;
    return this;
  }
  reset() {
    this.seconds = this.initialSeconds;
    return this;
  }
  update(update) {
    if (update.hasOwnProperty("seconds")) {
      this.seconds = update.seconds;
    }
    return this;
  }
  stop() {
    console.log(`Stoping timer: ${this.timerId}`);
    this.isRunning = false;
    return this;
  }
}

所以这就是我的问题所在。当然,你可以添加pad方法,甚至改变Timer对象的工作方式。我有一个完全不同的Timer类我想和这个TimerManager类一起使用。我只是创建了这个简单的,作为我自己的概念证明。如果有人对如何在javascript应用程序中管理多个计时器有任何更好的建议,请让我知道。

我也会避免使用parseInt()而不是Math.floor()来计算分钟。在jsBench上查看。Math.floor()的性能提高了70%。