倒计时器问题

时间:2017-09-06 15:11:50

标签: javascript php timer r-exams

我正在用PHP创建一个定时测试产品。我正面临着保持考试时间正常的问题。考试开始时,只要我在同一个屏幕上,计时器就能正常工作。但是当我在测试开启时打开其他屏幕(比如10分钟),并且在一段时间后回到测试时,计时器显示错误的时间并显示在前10分钟内消耗的测试时间仅为2分钟。 / p>

当我在测试开启时移出屏幕并在一段时间后回来时,只想知道为什么测试计时器的这种不稳定行为。

有人可以帮我吗?

PHP代码

<?php
/*Timer Code*/
        $dateFormat = "d F Y -- g:i a";
        $targetDate = time() + (240*60);//Change the 240 to however many minutes you want to countdown
        $actualDate = time();
        $secondsDiff = $targetDate - $actualDate;
        $remainingDay     = floor($secondsDiff/60/60/24);
        $remainingHour    = floor(($secondsDiff-($remainingDay*60*60*24))/60/60);
        $remainingMinutes = floor(($secondsDiff-($remainingDay*60*60*24)-($remainingHour*60*60))/60);
        $remainingSeconds = floor(($secondsDiff-($remainingDay*60*60*24)-($remainingHour*60*60))-($remainingMinutes*60));
        $actualDateDisplay = date($dateFormat,$actualDate);
        $targetDateDisplay = date($dateFormat,$targetDate);
?>

的JavaScript

/*Timer Code*/
  var days = <?php echo $remainingDay; ?>  
  var hours = <?php echo $remainingHour; ?>  
  var minutes = <?php echo $remainingMinutes; ?>  
  var seconds = <?php echo $remainingSeconds; ?> 

function setCountDown ()
{
  seconds--;
  if (seconds < 0){
      minutes--;
      seconds = 59
  }
  if (minutes < 0){
      hours--;
      minutes = 59
  }
  if (hours < 0){
      days--;
      hours = 23
  }
  document.getElementById("remain").innerHTML = "Time "+hours+" H : "+minutes+" M : "+seconds+" S";
  SD=window.setTimeout( "setCountDown()", 1000 );
  if (hours == '0' && minutes == '00' && seconds == '00') 
  { 
      seconds = "00"; window.clearTimeout(SD);
      timeStatus = 1;
      var response = window.alert("Time is up. Press OK to continue."); // change timeout message as required         
  } } // here is the end of setCountDown

3 个答案:

答案 0 :(得分:1)

这适用于我所列的更改:

PHP:

<?php
/*Timer Code*/
        $dateFormat = "d F Y -- g:i a";
        $targetDate = time() + (240*60);//Change the 240 to however many minutes you want to countdown
        $actualDate = time();
        $secondsDiff = $targetDate - $actualDate;
        $remainingDay     = floor($secondsDiff/60/60/24);
        $remainingHour    = floor(($secondsDiff-($remainingDay*60*60*24))/60/60);
        $remainingMinutes = floor(($secondsDiff-($remainingDay*60*60*24)-($remainingHour*60*60))/60);
        $remainingSeconds = floor(($secondsDiff-($remainingDay*60*60*24)-($remainingHour*60*60))-($remainingMinutes*60));
        $actualDateDisplay = date($dateFormat,$actualDate);
        $targetDateDisplay = date($dateFormat,$targetDate);
?>
  • PHP应该是开放的

JavaScript的:

/*Timer Code*/
  var days = 0;
  var hours = 4;
  var minutes = 0;
  var seconds = 0;

  setCountDown();

function setCountDown ()
{
  seconds--;
  if (seconds < 0){
      minutes--;
      seconds = 59
  }
  if (minutes < 0){
      hours--;
      minutes = 59
  }
  if (hours < 0){
      days--;
      hours = 23
  }
  if (hours == '0' && minutes == '00' && seconds == '00') 
  { 
      seconds = "00"; 
      window.clearTimeout(SD);
      timeStatus = 1;
      var response = window.alert("Time is up. Press OK to continue."); // change timeout message as required         
  } 
  console.log(days+'/'+hours+'/'+minutes+'/'+seconds);
  SD=setTimeout(setCountDown, 1000);
}
  • setCountDown错过了它的结束括号
  • 应该仅使用函数名称调用setTimeout。在名称将返回的值传递给setTimeout后,用()调用它,而不是函数本身。 (最后一点与您的问题无关,因为您在引号中使用了函数调用)
  • 在您检查是否为0之后,应该重新调用该函数。

对于更准确的计时器系统,请考虑使用服务器和用户计算机的时间戳,而不是可以操作的变量。然后,您可以连续从用户的计算机中提取当前时间,以查看已经过了多长时间。

答案 1 :(得分:1)

当不在前台运行时,JavaScript不会总是处理计时器滴答,所以这就是你减速的原因。

如果您愿意,那将更可靠:

  • 在JS中使用目标截止日期,每次处理计时器事件时,您将转换为剩余时间。这种方式总是与实际截止日期有关。
  • 不时从服务器刷新截止日期信息(不是每隔一秒,但可能每隔5分钟)。这意味着你必须在服务器端使用某种持久性,比如一个会话范围变量,它具有可以返回剩余秒数的截止时间。
  • 在服务器端验证在截止日期之后没有提交答案(如果有人篡改了客户端)。同样,您需要一些会话范围用于实现此目的。

我不会提供第二个或第三个想法的代码,但这里是适合第一个想法的代码(这可能足以满足您的目的?):

/*Timer Code*/
var totalSeconds = 240*60; //<?php echo 240*60; ?>  
var deadlineMillis = Date.now() + totalSeconds * 1000;

function setCountDown () {
    var secondsRemaining = Math.max(0, Math.round((deadlineMillis - Date.now()) / 1000)),
        minutes = Math.floor(secondsRemaining / 60),
        hours = Math.floor(minutes / 60),
        days = Math.floor(hours / 24);
    hours = hours % 24;
    minutes = ('0' + (minutes % 60)).substr(-2);
    seconds = ('0' + (secondsRemaining % 60)).substr(-2);
    document.getElementById("remain").textContent = 
        "Time "+hours+" H : "+minutes+" M : "+seconds+" S";
    if (secondsRemaining === 0) { 
        timeStatus = 1;
        alert("Time is up. Press OK to continue."); // change timeout message as required
        return;
    }
    setTimeout(setCountDown, 1000);
}

setCountDown();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="remain"></div>

用PHP生成的值替换240*60

答案 2 :(得分:0)

大多数现代浏览器故意将低优先级放在非活动选项卡/窗口上。因此计时器将减慢速度。所以你面对的不是不稳定的行为。它旨在提高浏览器性能。

https://developers.google.com/web/updates/2017/03/background_tabs#budget-based_background_timer_throttling

https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout#Timeouts_in_inactive_tabs_throttled_to_&GT; 1000ms的

解决方案:使用网络工作者