如何根据服务器响应启动计时器



我想根据服务器响应启动倒计时计时器。我首先为一个本地测试做了一个计时器,在这个测试中,我通过了员工姓名、小时、分钟和秒。它运行得很好。但现在我想启动倒计时计时器作为服务器数据。它将在一分钟内获取员工姓名和倒计时计时器时间。但它并没有正确地拆分json对象。它显示var有未定义的数据。

API响应-[{"EmployeeName":"Abc","Hour":9,"Min":25},{"EmployeeName":"Xyz","Hour":11,"Min":41}]

Javascript

function GetMachine() {
var http = new XMLHttpRequest();
var url = 'php/StitchTimer.php';
http.open('GET', url, true);
http.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
http.onreadystatechange = function() {//Call a function when the state changes.
if(http.readyState == 4 && http.status == 200) {
var data = http.responseText;
var jsonResponse = JSON.parse(data);
for(var i=0;i<jsonResponse.length;i++){
var index = jsonResponse[i];
console.log(index);
var empname = index["EmployeeName"];
var hour = index["Hour"];
var minute = index["Min"];

addEmployee(empname,hour,minute);
}
}
http.send();
}
}
function addEmployee(emp,hr,mi)
{ 
var employee = new Employee(emp,hr,mi,00);
employeeList.appendChild(employee.domObj);
employee.startTimer();
}
class Employee
{   
constructor(name,hr,min,sec)
{
var self=this;
this.timer;
this.timeInSec;
this.domObj=document.createElement("div");
this.timeSpan=document.createElement("span");
this.domObj.style.backgroundColor = '#4CA';
this.domObj.style.border = 'none';
this.domObj.style.height = '100px';
this.domObj.style.width = '100px';
this.domObj.style.color = 'white';
this.domObj.style.padding = '20px';
this.domObj.style.textAlign = 'center';
this.domObj.style.textDecoration = 'none';
this.domObj.style.display = 'inline-block';
this.domObj.style.fontSize = '26px';
this.domObj.style.borderRadius = '50%';
this.domObj.style.margin = '20px';
this.domObj.style.justifyContent = "center";
this.timeInSec=hr*60*60+min*60+parseInt(sec);
this.timeSpan.innerHTML=hr+":"+min+":"+sec;
this.domObj.innerHTML=name+"<br>";
this.domObj.appendChild(this.timeSpan);
console.log("0:"+this.timeInSec);
}               
startTimer()
{
this.timer=setInterval(this.updateTime.bind(this),1000);
}
updateTime()
{
var hr,min,sec,temp;
if (this.timeInSec<=0)
{
clearInterval(this.timer);
}
else
{
this.timeInSec--;
//console.log("1:"+this.timeInSec);
sec=this.timeInSec % 60;
temp=this.timeInSec-sec;
temp/=60;
//console.log("2:"+temp);
min=temp % 60;
temp-=min;
hr=temp/60;
this.timeSpan.innerHTML=hr+":"+min+":"+sec;
}
}
}

PHP代码

<?php
date_default_timezone_set('Asia/Kolkata');
$con = mysqli_connect("localhost","username","pw","db");
$currenttime = date("Y-m-d H:i");
$sql = "SELECT * FROM `Stitch` WHERE `EndTime` > '$currenttime' ";
$res = mysqli_query($con,$sql);
$result = array();
while($row = mysqli_fetch_array($res))
{
$end = $row['EndTime'];
$end = strtotime($end);
$current = strtotime($currenttime);
$timer = $end-$current;
$timer = $timer/60;
$hour = floor($timer/60);
$min = $timer-($hour*60);
$result[]=array('EmployeeName' =>$row['WorkerName'],'Hour'=>$hour,'Min'=>$min);
}
echo json_encode($result);
mysqli_close($con);
?>

我不确定您最初的问题是什么,但您可以通过多种方式简化解决方案。

1:使用Fetch API

Fetch API在所有现代浏览器中都可用,IE10浏览器有一个polyfill。它为在浏览器中获取资源提供了一个干净得多的界面——不需要处理readyState和响应代码。

fetch(url)
.then(function(response){
// return the response as JSON
return response.json();
})
.then(function(data){
// use the JSON data here
})
.catch(function(err){
console.log('Request failed', err);
});

fetch()将数据URL作为参数,并返回Promise。如果fetch()操作成功完成,响应将传递给then()链,否则我们将有一个错误需要处理。

2:利用JSON

从服务器返回的数据被解析为JSON。不需要复制单个元素来构造新对象,因为您已经有了这样的对象的数组。

假设服务器的响应是:

[{"EmployeeName":"Abc","Hour":9,"Min":25},{"EmployeeName":"Xyz","Hour":11,"Min":41}]

然后data将是一个包含该精确结构的数组对象,您可以使用forEach()方法迭代数组的元素。

data.forEach(function(item){
// item is the current element being processed
console.log(item.EmployeeName);
// Output:
// "Abc"
// "Xyz"
});

data对象包含初始状态,没有什么可以阻止您更改它以满足您的需求。请记住,如果您试图访问一个不存在的值或属性,它将被分配一个类型为undefined的值。

3:计时器有成本

您的解决方案为数组中返回的每个单独元素声明一个计时器。如果您需要显示1000个项目,那么就需要声明1000个计时器。或者,您可以实现一个单独的计时器,并让处理程序遍历元素集合,更新每个元素的时钟。

4:浏览器可以设置内容样式

这只是个小问题。与其为每个动态创建的元素设置相同的样式属性,不如定义一个CSS规则或添加一个样式标记,并将适当的CSS类添加到新的HTML元素中。有关更多详细示例,请参见Element.classList。

var divElement = document.createElement('div');
divElement.classList.add('div-class-name');

这里是一个不需要Employee类的实现,并且使用如上所述的单个定时器。使用DOM元素上的数据属性来跟踪各个时钟的状态,但它也可以很容易地记录在原始data对象中。

要试用代码,请将dataUrl变量设置为数据源的正确URL。

JavaScript:

(function(){
var dataUrl = ''; // where the data comes from
var containerId = 'timers-container'; // existing container element in the DOM
var activeClocksSelector = '#timers-container .timer-str.active';
var dataAttrSeconds = 'data-seconds';
var countdownTimerId;
// helper to zero pad time elements
function getZeroPaddedValue(value) {
return (value < 10) ? '0' + value : value; 
}
// returns a correctly formatted time string
function getFormattedTimeString(secondsParam) {
var secondsNum = parseInt(secondsParam, 10);
var hours = Math.floor(secondsNum / 3600);
var minutes = Math.floor((secondsNum - (hours * 3600)) / 60);
var seconds = secondsNum - (hours * 3600) - (minutes * 60);
return getZeroPaddedValue(hours) + ':' + getZeroPaddedValue(minutes) + 
':' + getZeroPaddedValue(seconds);
}
// convert time elements to a number of seconds
function getCountdownSeconds(hours, minutes, seconds) {
var hh = (typeof hours !== 'undefined') ? parseInt(hours, 10) * 3600 : 0;
var mm = (typeof minutes !== 'undefined') ? parseInt(minutes, 10) * 60 : 0;
var ss = (typeof seconds !== 'undefined') ? parseInt(seconds, 10) : 0;
return hh + mm + ss;
}
// setInterval callback handler
function updateCountdownClocks() {
var element, i, seconds;
// get the active countdown clock elements
var activeClockElements = document.querySelectorAll(activeClocksSelector);
var numActiveClocks = activeClockElements.length;
if (numActiveClocks > 0) {
// loop through the elements
for (i=0; i < numActiveClocks; i++) {
element = activeClockElements[i];
seconds = 0; // use a sensible default
// check that the 'data-seconds' attribute is present
if (element.hasAttribute(dataAttrSeconds)) {
// decrement the number of seconds
seconds = parseInt(element.getAttribute(dataAttrSeconds), 10) - 1;
}
// update the 'data-seconds' attribute
element.setAttribute(dataAttrSeconds, seconds);
// update the UI
element.textContent = getFormattedTimeString(seconds);
// check if counter needs to remain active
if (seconds < 1) {
element.classList.remove('active');
}
}
} else {
// remove the timer because the active clocks collection is empty
clearInterval(countdownTimerId);
}
}
// creates the DOM structure
function setApplicationState(data) {
// Are there items in the array?
if (0 < data.length) {
// get a handle on the DOM container element
var container = document.getElementById(containerId);
// use DocumentFragment object for efficiency
var fragment = document.createDocumentFragment();
// iterate through the array of data items
data.forEach(function(item){
// determine the number of seconds in the countdown timer
var seconds = getCountdownSeconds(item.Hour, item.Min);
// create HTML elements
var outerDiv = document.createElement('div');
var innerDiv = document.createElement('div');
// populate outer div content
outerDiv.classList.add('timer-block');
outerDiv.textContent = item.EmployeeName;
// populate inner div content
innerDiv.classList.add('timer-str');
// add a class to indicate the item is active
if (0 < seconds) {
innerDiv.classList.add('active');
}
// initialise the 'data-seconds' attribute
innerDiv.setAttribute(dataAttrSeconds, seconds);
innerDiv.textContent = getFormattedTimeString(seconds);
// append the HTML elements
outerDiv.appendChild(innerDiv);
fragment.appendChild(outerDiv);
});
// add the DocumentFragment to the DOM
container.appendChild(fragment);
}
// must return a value
return data;
}
// start the countdown clocks
function startTheTimer(data) {
// keep track of the interval ID
countdownTimerId = setInterval(updateCountdownClocks, 1000);
// promise chain must return a value
return data;
}
// using the Fetch API to retrieve the initial state
var state = fetch(dataUrl)
.then(function(response){
// return the parsed JSON content
return response.json();
})
.then(setApplicationState)
.then(startTheTimer)
.catch(function(err){
console.log('Request failed', err);
});
})();

CSS:

#timers-container .timer-block {
background-color: #4CA;
border: none;
border-radius: 50%;
color: white;
display: inline-block;
font-size: 26px;
height: 100px;
justify-content: center;
margin: 20px;
padding: 20px;
text-align: center;
text-decoration: none;
width: 100px;
}

HTML:

<div id="timers-container"></div>

最新更新