2011-04-28 99 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