2011-04-28 96 views
0

嗯,我试图重新在这里看到每个这些挑战的倒计时: http://www.bungie.net/stats/reach/globalchallenges.aspx问题的JavaScript倒计时

的问题是,如果你比较my countdownoriginal countdown有大约10-14秒的差别,我只是不明白为什么?谢谢!

我正在使用其来源mobile page(查看源代码)来获取到期时间。

<span id="wExpSeconds" title="1304330400000"></span> 
<span id="dExpMilliseconds" title="1303984800000"></span> 

这是我的倒数网页的源代码:

<html> 
    <head> 
     <title></title> 
     <style type="text/css"> 
     .stat{ font: 14px/18px Arial, Helvetica, sans-serif; color:#bbb; } 
     .seconds{ color:#ff5f3c; } 
     </style> 
    </head> 
    <body> 

     <div id="countDownDiv"></div> 

     <script type="text/javascript"> 
     function countDown(id, end, cur){ 
      this.container = document.getElementById(id); 
      this.endDate = new Date(end); 
      this.curDate = new Date(cur); 


      var context = this; 

      var formatResults = function(day, hour, minute, second){ 
      var displayString = [ 
       '<span class="stat">',day,'d </span>', 
       '<span class="stat">',hour,'h </span>', 
       '<span class="stat">',minute,'m </span>', 
       '<span class="stat seconds">',second,'s</span>' 
      ]; 
      return displayString.join(""); 
      } 

      var update = function(){ 
       context.curDate.setSeconds(context.curDate.getSeconds()+1); 

       var timediff = (context.endDate-context.curDate)/1000; 

       // Check if timer expired: 
       if (timediff<0){ 
        return context.container.innerHTML = formatResults(0,0,0,0); 
       } 

       var oneMinute=60; //minute unit in seconds 
       var oneHour=60*60; //hour unit in seconds 
       var oneDay=60*60*24; //day unit in seconds 

       var dayfield=Math.floor(timediff/oneDay); 
       var hourfield=Math.floor((timediff-dayfield*oneDay)/oneHour); 
       var minutefield=Math.floor((timediff-dayfield*oneDay-hourfield*oneHour)/oneMinute); 
       var secondfield=Math.floor((timediff-dayfield*oneDay-hourfield*oneHour-minutefield*oneMinute)); 

       context.container.innerHTML = formatResults(dayfield, hourfield, minutefield, secondfield); 

       // Call recursively 
       setTimeout(update, 1000); 
      }; 

      // Call the recursive loop 
      update(); 
      } 

     countDown("countDownDiv",1304330400000, new Date().getTime()); 
     </script> 
    </body> 
</html> 
+0

我只显示一个6秒的差异 – 2011-04-28 01:31:08

+1

由于它们在一个线程中执行的事实,JavaScript定时器是不可靠的:http://ejohn.org/blog/how-javascript-timers-work/。不知道这是否是您的问题,但很高兴知道您是否期望计时器正确执行*。 – 2011-04-28 01:40:21

+0

很奇怪,我看到在时间上的精确匹配 – 2011-04-28 01:53:42

回答

0
<script type="text/javascript"> 
    function countDown(id, end, cur){ 
     this.container = document.getElementById(id); 
     this.endDate = new Date(end); 
     this.curDate = new Date(cur); 

由于函数不调用任何对象的方法,也不能与call()apply(),其此关键字将引用全局对象。所以上面有效地为container,endDate和curDate创建了全局变量。

 var context = this; 

请写出1000次:this关键字不是上下文(也不有什么用范围做)。

  ... 
     context.curDate.setSeconds(context.curDate.getSeconds()+1); 

如前所述,变量“context”是对全局对象的引用,它由您如何调用函数来设置。所以你在这里访问全局变量。

  ... 
     // Call recursively 
     setTimeout(update, 1000); 

这是你的问题。这将在关于 1秒更新。计数器运行的时间越长,它会变得越不准确(它总会在后面漂移)。

你应该每次都得到一个新的日期对象,看看ms,然后在下一个整秒之后调用下一个超时(给它大约30到50ms以确保它刚好在之后而不是之前)。这样,你的柜台永远不会太多,即使是这样,它每次调用它时都会自行更正。

并确保您每次计算完整的计数,所以如果有几秒的滞后,您再次追赶。

+1

你必须停止这个“这个“不是上下文”的争论或解释你的意思更好。 “语境”一词在英语中具有一般意义,在此明确适用。这是MDC文档和JavaScript开发人员普遍使用的词。你不必要地混淆了人。 – 2011-04-28 03:40:14

+0

他们很困惑。ECMAScript有一个*执行上下文*,* this *关键字是该上下文中的一个标识符,可能包含数百或数千个激活对象和作用域链上的其他变量和参数,它们一起可能被称为“上下文”。单挑出这个代表上下文无关紧要。在[clj](http://groups.google.com/group/comp.lang.javascript/topics?gvc=2)或[jsMentors](http://groups.google.com/group/jsmentors/topics)中讨论) 如果你希望。 – RobG 2011-04-28 04:08:20