【发布时间】:2021-09-13 10:45:04
【问题描述】:
我有以下 Javascript 代码
// COUNTDOWN TIMER
function refillTimer(refillTimer){
var countDownDate = new Date(refillTimer).getTime();
var x = setInterval(function() {
var now = new Date().getTime();
var distance = countDownDate - now;
var hours = ("0" + Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60))).slice(-2);
var minutes = ("0" + Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60))).slice(-2);
var seconds = ("0" + Math.floor((distance % (1000 * 60)) / 1000)).slice(-2);
document.getElementById("refillTimer").innerHTML = hours + ":" + minutes + ":" + seconds;
if(distance < 0){
clearInterval(x);
document.getElementById("refillTimer").innerHTML = "00:00:00";
}
}, 1000);
}
// ON SWIPE PERFORM ACTION
async function swipeAction(currentElementObj, swipeType) {
var cardId = currentElementObj.getAttribute("value");
var dataString = {
card: cardId,
swipe: swipeType
};
let response = await new Promise((resolve, reject) => {
try {
var xhr = new XMLHttpRequest();
xhr.open("POST", "processes/swipe.php", true);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.responseType = "json";
xhr.send(JSON.stringify(dataString));
xhr.onreadystatechange = function () {
let resObj = xhr.response;
if(xhr.readyState == 4 && xhr.status == 200 && resObj) {
if(resObj.action == 'gameover'){
refillTimer(resObj.nextgameoverTimer);
}else if(resObj.action == 'killsalloted'){
refillTimer(resObj.nextkillsallotedTimer);
}
}
};
}catch(e){
reject(e.toString());
}
});
}
正如您在swipeAction() 函数中看到的那样,我有两个if 和else if 成功条件,我调用计时器。这里的问题是,一旦在一种条件下调用定时器,然后在另一种条件下调用定时器就会相互重叠。这不应该发生。计时器应单独加载。这在技术上意味着每次调用计时器函数或类似的东西时都应该刷新它。请查看下面的 GIF 以了解具体问题。
这里,一个条件调用 12 小时定时器,而另一个调用 24 小时定时器。如上所示,两个计时器相互重叠,而不是仅显示各自的计时器。需要的解决方案是什么?
【问题讨论】:
-
每次刷卡时都会安装一个新的间隔计时器,因此每秒内会触发多个不同的计时器。确保通过从
refillTimer返回或将其存储在外部范围或全局变量中来保存计时器 ID (x),并在设置下一个之前将其存储在clearInterval中,而不仅仅是在distance时低于零。 -
尝试使
refillTimer更普通,从外部传递区间 ID 和日期对象,因为每次调用函数时都会创建一个新的 inteeval ID 和日期对象。 -
@Amadan 和 Kingbeencent 的代码答案会很容易理解和赞赏
标签: javascript timer xmlhttprequest