倒数计时器不适用于AJAX

时间:2016-07-04 21:20:26

标签: javascript ajax

我正在尝试用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);

3 个答案:

答案 0 :(得分:2)

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);
}

答案 1 :(得分:0)

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

请参阅https://www.sitepoint.com/creating-accurate-timers-in-javascript/

How to create an accurate timer in javascript?

&#13;
&#13;
<!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>
&#13;
&#13;
&#13;

答案 2 :(得分:0)

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

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;