【问题标题】:Countdown Timer Objects - Javascript倒数计时器对象 - Javascript
【发布时间】:2013-01-03 20:52:55
【问题描述】:

我想在 Javascript 中创建一个简单的计时器,它从给定时间倒计时直到它达到 0。我发现这个 tutorial 工作得很好。我的问题是我需要在同一页面上放置多个计时器。本教程显然不会这样做,因为它使用全局变量(我是 JS/Programming 的新手,所以我可能没有使用正确的术语)。我试图重新创建相同的东西,只创建每个计时器作为它自己的对象,这样它们就不会相互干扰。这就是我所拥有的。

function taskTimer(name, startTime) {
  this.timer = name;
  this.totalSeconds = startTime;
  this.tick = function() {
    if (this.totalSeconds <= 0) {
      return;
    }
    this.totalSeconds -= 1;
    this.updateTimer();
    // window.setTimeout("this.tick()", 1000);
  };
  this.updateTimer = function(){
    this.seconds = this.totalSeconds;

    this.hours = Math.floor(this.seconds / 3600);
    this.seconds -= this.hours * (3600);

    this.minutes = Math.floor(this.seconds / 60);
    this.seconds -= this.minutes * (60);

    this.timeString = this.leadingZero(this.hours) + ":" + this.leadingZero(this.minutes) + ":" + this.leadingZero(this.seconds);
    return this.timeString;
  };
  this.leadingZero = function(time){
    return (time < 10) ? "0" + time : + time;
  };
}
var testTimer = new taskTimer("timer", 30);
testTimer.tick();

我最后在那里创建了一个。跑步 testTimer.updateTimer(); 返回 00:00:30 这是正确的,但运行 testTimer.tick(); 不会返回任何值。这部分代码显然有问题,我就是想不通。

【问题讨论】:

  • 如何判断这是否有效?您没有在任何地方绘制任何计时器值。
  • 因为updateTimer方法有效,所以调用tick方法应该返回相同的值,因为它调用了它内部的updateTimer方法。
  • "testTimer.tick(); 没有返回值" 这是您要解决的问题吗?如果是这样,该函数永远不会返回任何内容。你需要一个return 声明。
  • 但是 testTimer.tick();调用 updateTimer();确实返回值的方法。这不应该意味着 testTimer.tick();会返回相同的值吗?
  • @SMDeConto updateTimer 返回一个值来打勾,但打勾不会把它返回给你。

标签: javascript object counter


【解决方案1】:

您遇到了一些问题。

  1. 您在 tick 方法中调用了 updateTimer(),所以它 除非您归还,否则永远无法到达那里。
  2. 使用您当前的设置,每次您想要更新时钟时都必须手动调用tick,如果您不准确地每隔一秒执行一次,则计时器将不准确。
  3. 要使用#2,您不应该像现在这样减少totalSeconds,因为不能保证在您的超时触发之间恰好是一秒。请改用日期。

我会这样做:http://jsfiddle.net/R4hnE/3/

// I added optional callbacks. This could be setup better, but the details of that are negligible. 
function TaskTimer(name, durationInSeconds, onEnd, onTick) {
    var endTime,
        self = this, // store a reference to this since the context of window.setTimeout is always window
        running = false;
    this.name = name;
    this.totalSeconds = durationInSeconds;

    var go = (function tick() {
        var now = new Date().getTime();
        if (now >= endTime) {
            if (typeof onEnd === "function") onEnd.call(self);
            return;
        }
        self.totalSeconds = Math.round((endTime - now) / 1000); // update totalSeconds placeholder
        if (typeof onTick === "function") onTick.call(self);
        window.setTimeout(tick, 1000 / 12); // you can increase the denominator for greater accuracy. 
    });

    // this is an instance method to start the timer
    this.start = function() {
        if (running) return; // prevent multiple calls to start

        running = true;
        endTime = new Date().getTime() + durationInSeconds * 1000; // this is when the timer should be done (with current functionality. If you want the ability to pause the timer, the logic would need to be updated)
        go();
    };
}
// no reason to make this an instance method :)
TaskTimer.prototype.toTimeString = function() {
    var hrs = Math.floor(this.totalSeconds / 60 / 60),
        min = Math.floor(this.totalSeconds / 60 - hrs * 60),
        sec = this.totalSeconds % 60;

    return [hrs.padLeft("0", 2), min.padLeft("0", 2), sec.padLeft("0", 2)].join(" : ");
};

var task = new TaskTimer("task1", 30, function() {
    document.body.innerHTML = this.toTimeString();
    alert('done');
}, function() {
    document.body.innerHTML = this.toTimeString();
});

【讨论】:

  • 另请注意,约定将类以大写字母开头。
  • 我会努力理解这一点,哈哈。另外,我正在尝试同时运行多个计时器。
  • 太棒了。我还不明白,但我会明白的:)谢谢!
  • @SMDeConto 你有什么具体问题吗?
  • 我敢肯定,但到目前为止,我很高兴弄清楚您使用的一些方法/语法。我刚开始上学,我想在休息时间自己做一些独立的学习,所以我为自己创建了这个项目。我认为阅读别人的代码对我很有帮助。如果有什么我想不通的,我会告诉你的。谢谢!
【解决方案2】:

this 总是有问题,在一个例子中,我不得不在函数中重新定义它:

this.tick = function() {
  self=this;
  if (self.totalSeconds <= 0) {
    return;
  }
  self.totalSeconds -= 1;
  self.updateTimer();
   // window.setTimeout("self.tick()", 1000);
};

这是另一篇关于此的帖子:var self = this?

【讨论】:

  • 实际上你在你提供的代码中不需要这个。但是当你使用回调时,比如 setTimeout 或其他 - 你确实需要它(似乎你想通过评论来突出它)
  • 为什么要引用打勾?我认为这更干净一点:setTimeout(self.tick, 1000);
  • 您将 self 声明为全局变量。啧啧。
  • 我只评论了它,因为我正在测试tick方法并且不希望它再次运行。这对我也不起作用,它只是冻结了。
【解决方案3】:

我的版本,你可以在: http://fiddle.jshell.net/hmariod/N7haK/4/

var tmArray = new Array();
var timerRef, timerId=0;


function newTimer(){
    try{
        if(tmArray.length > 4) throw "Too much timers";
        var countDown = parseInt(document.getElementById("tCountown").value,10);
        if(isNaN(countDown)) throw "tCountown is NaN";
        var tmName = document.getElementById("tName").value;
        var nt = new taskTimer(++timerId, tmName, countDown);
        createTmElement(timerId, tmName);
        tmArray.push(nt);
        if(!timerRef) timerRef = setInterval(timerFn, 1000);
        showTimers();
    }catch(er){
        alert("newTimer:" + er);
    }
}

function taskTimer(id, name, tCountown) {
    this.id = id;
    this.tName = name;
    this.tCountown = tCountown;
}


function timerFn(){
    try{
        var i;
        killTimer = true;
        for(i = 0; i < tmArray.length; i++){
           tmArray[i].tCountown--;
            if(tmArray[i].tCountown < 0){
                tmArray[i].tCountown = 0;
            }else{
                killTimer = false;
            }
        }
        if(killTimer) clearInterval(timerRef);
        showTimers();
    }catch(er){
        clearInterval(timerRef);
        aler("timerFn: " + er);
    }
}

【讨论】:

    猜你喜欢
    • 2011-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多