倒计时计时器不能与AJAX一起工作

Count down timer not working with AJAX

本文关键字:一起 工作 AJAX 计时器 不能 倒计时      更新时间:2023-09-26

我正试图用JS做一个计数器。到目前为止,我已经成功地实现了这一点,但是我现在遇到了一个问题。在使用AJAX检索倒计时时间时,我无法使其工作。这很奇怪,因为它可以在我的原始文件上工作,但不能与AJAX调用的php文件。

这个可以正常工作:https://jsfiddle.net/6kvp25vv/

我不知道是什么问题。这是HTML页面:

<button onclick="upgrade('meat_max')" id="up_meat_max">+</button>

当我点击按钮时,它运行这个js文件中的函数,它在upgrade.php上创建一个GET请求:

function upgrade(building) {
  var file = 'upgrade.php?building=' + building;
  ajax(file, function(response) {
    document.getElementById('construction').innerHTML += response;
  })
}
function ajax(file, fn) {
  var xmlhttp = new XMLHttpRequest();
  xmlhttp.onreadystatechange = function() {
    if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
      fn(xmlhttp.responseText);
    }
  };
  xmlhttp.open('GET', file, true);
  xmlhttp.send();
}

这是upgrade.php中的代码(通过AJAX发送到该文件的变量不用于测试代码):

<div class="time">Time: <span id="timer">?</span></div>
  var hour = 2;
  var minute = 46;
  var second = 45;
  // function to make a counter
  function clockIt() {
    function clockO(digit) {
      if(digit<10) {
        return '0';
      } else {
        return '';
      }
    }
    document.getElementById('timer').textContent = hour + ':' + clockO(minute) + minute + ':' + clockO(second) + second;
    if(second>0) {
      second -= 1;
    } else if(minute>0) {
      minute -= 1;
      second += 59;
    } else if(hour>0) {
      hour -= 1;
      minute += 59;
    }
  }
  // runs the function every seconds
  clockIt();
  setInterval(function (){clockIt()}, 1000);

innerHTML不执行ajax加载的脚本,我在你的情况下会做的是返回一个JSON编码的字符串,你需要的变量,并有一个函数在你的主脚本(一个已经加载)与此提供的脚本,这样你已经有函数准备好,只传递参数与ajax响应。

你可以用

解码json字符串:
obj = JSON.parse(jsonString);
例如:

Ajax JSON响应字符串:
{"time": {"hour":2, "minute":46, "second": 45}, "html": "<div class='"time'">Time: <span id='"timer'"></span></div>"}

修改后的升级功能:

function upgrade(building) {
  var file = 'upgrade.php?building=' + building;
  ajax(file, function(response) {
    obj = JSON.parse(response);
    time = obj.time;
    document.getElementById('construction').innerHTML += obj.html;
    startCountdown(time.hour, time.minute, time.second);
  })
}

新功能

function startCountdown(hour, minute, second) {
    // function to make a counter
    function clockIt() {
      function clockO(digit) {
        if(digit<10) {
          return '0';
        } else {
          return '';
        }
     }
    document.getElementById('timer').textContent = hour + ':' +     clockO(minute) + minute + ':' + clockO(second) + second;
     if(second>0) {
        second -= 1;
     } else if(minute>0) {
       minute -= 1;
       second += 59;
     } else if(hour>0) {
       hour -= 1;
       minute += 59;
     }
 }
 // runs the function every seconds
 clockIt();
 setInterval(function (){clockIt()}, 1000);
}

我的问题是倒计时计时器的方法。当您指定间隔为1000毫秒时,您不能指望它是1000毫秒。实际上,当计时器循环在1000毫秒后到达它的时候。在一段时间内,会有一些延误。如果你想要精确计时,你要做的就是存储初始设置,然后测量从倒计时开始到当前时间的时间。请参阅下面的代码,其中计时器基于内部时钟而不是间隔计数器。一旦你有了秒数,你可以很容易地把它转换成小时、分钟和秒,用3600除以小时,用除法和模数计算分和秒。

见https://www.sitepoint.com/creating-accurate-timers-in-javascript/

如何在javascript中创建一个准确的计时器?

<!DOCTYPE html />
<html>
<head>
  <meta encoding="UTF-8" />
  <title>Testing XMLHttpRequest</title>
  <script>
    var request;
    var button1;
    var display1;
    var display2;
    var display3;
    var start;
    var counter;
    function second() {
      display2.value = display2.value + "'r'nreadyState=" + request.readyState + " status=" + request.status + "'r'n";;
      if (request.readyState == 4 && request.status == 200) {
        display1.value = display1.value + request.responseText + "'r'n";
      }
    }
    function first() {
      display2.value = display2.value + "'r'n" +
        "Starting page     'r'n";
      request = new XMLHttpRequest();
      request.onreadystatechange = second;
      var file = "http://localhost:80/";
      request.open('GET', file, true);
      request.send();
      setInterval(timed, 1000);
    }
    function starter() {
      display1 = document.getElementById("display1");
      display2 = document.getElementById("display2");
      display3 = document.getElementById("display3");
      button1 = document.getElementById("button1");
      button1.onclick = first;
      start = new Date();
      counter = 60;
    }
    function timed() {
      var duration = (start.getTime() - new Date().getTime()) / 1000.0;
      display3.value = (duration + counter).toFixed(0);
    }
    window.onload = starter;
  </script>
</head>
<body>
  <form>
    <p>
      <input type="button" id="button1" value="Start" />Timer:
      <input type="text" readonly="readonly" id="display3" />
    </p>
    <p>Status:
      <textarea rows="5" cols="30" id="display2"></textarea>
    </p>
    <p>Response:
      <textarea rows="60" cols="80" id="display1"></textarea>
    </p>
  </form>
</body>
</html>

找到了一种补偿延迟的方法,使用原始版本:

function upgrade(building) {
  var file = 'upgrade.php?building=' + building;
  ajax(file, function(response) {
    var obj = JSON.parse(response);
    var time = obj.time;
    document.getElementById('construction').innerHTML += obj.html;
    run_clockIt(time.hour, time.minute, time.second);
  })
}
// general AJAX launcher
function ajax(file, fn) {
  var xmlhttp = new XMLHttpRequest();
  xmlhttp.onreadystatechange = function() {
    if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
      fn(xmlhttp.responseText);
    }
  };
  xmlhttp.open('GET', file, true);
  xmlhttp.send();
}

// count down timer with adjustments to compensate delay
function clockIt(hour, minute, second, finished, nbOfLoop) {
  // every 5 seconds, run a delay correction
  if(nbOfLoop%5 == 0) {
    var actualTimeLeft = adjustClock(finished);
    minute = actualTimeLeft[0];
    second = actualTimeLeft[1];
  }
  nbOfLoop += 1;
  // add a string "0" if necessary
  function clockO(digit) {
    if(digit<10) {
      return '0';
    } else {
      return '';
    }
  }
  document.getElementById('timer').textContent = hour + ':' + clockO(minute) + minute + ':' + clockO(second) + second;
  // update displayed timer
  if(second>0) {
    second -= 1;
  } else if(minute>0) {
    minute -= 1;
    second += 59;
  } else if(hour>0) {
    hour -= 1;
    minute += 59;
  }
  // waits 1 sec before launching the next one
  setTimeout(function() {
    clockIt(hour, minute, second, finished, nbOfLoop);
  }, 1000);
}
// runs the function for the first time
function run_clockIt(hour, minute, second) {
  var finished = new Date();
  finished.setUTCHours(finished.getUTCHours() + hour);
  finished.setUTCMinutes(finished.getUTCMinutes() + minute);
  finished.setUTCSeconds(finished.getUTCSeconds() + second);
  clockIt(hour, minute, second, finished, 1);
}
function adjustClock(finished) {
  var now = new Date();
  var diff = new Date(Math.abs(now - finished));
  return [diff.getUTCMinutes(), diff.getUTCSeconds()];
}

这样,倒计时计时器是平滑的,没有滞后,最重要的是你可以定义调整功能将运行和纠正计时器的间隔。

这是php文件,准备JSON对象(感谢@Miguel):
<?php
header('Content-Type: application/json');
// retreive variables from AJAX call
$building = $_REQUEST['building'];
// processing variable with database...
// prepare JSON object
$jsonData = '
{
  "time":{"hour":2, "minute":46, "second": 45},
  "html": "<div class='"time'">Time: <span id='"timer'"></span></div>"
}
';
echo $jsonData;