Проблемы с обратным отсчетом JavaScript - PullRequest
0 голосов
/ 28 апреля 2011

Что ж, я пытаюсь воссоздать обратный отсчет для каждого из следующих вызовов: http://www.bungie.net/stats/reach/globalchallenges.aspx

Проблема в том, что если сравнить мой отсчет с исходным отсчетом разница в 10-14 секунд, я просто не понимаю, почему?Спасибо!

Я использую источник с их мобильной страницы (просмотреть исходный код), чтобы узнать время истечения срока действия.

<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>

1 Ответ

0 голосов
/ 28 апреля 2011
   <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(), ее ключевое слово this будет ссылаться на глобальный объект.Таким образом, вышеприведенное эффективно создает глобальные переменные для container, endDate и curDate.

        var context = this;

Пожалуйста, запишите 1000 раз: это ключевое слово не является контекстом (и не имеет к нему никакого отношенияscope).

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

Как уже обсуждалось, переменная "context" является ссылкой на глобальный объект, она задается тем, как вы вызываете функцию.Итак, вы обращаетесь к глобальным переменным здесь.

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

Вот ваша проблема.Это вызовет обновление через около 1 секунды.Чем дольше работает ваш счетчик, тем более неточным он станет (он всегда будет дрейфовать позже).

Вы должны каждый раз получать новый объект даты, смотреть мс, а затем вызывать следующий таймаут сразу после следующегополная секунда (дайте ей от 30 до 50 мс, чтобы убедиться, что это только после, а не раньше).Таким образом, ваш счетчик никогда не выйдет из строя, и даже если он есть, он будет исправляться каждый раз, когда его вызывают.

И убедитесь, что вы каждый раз рассчитываете полный отсчет, так что если есть задержканесколько секунд вы снова догоняете.

...