如何使用javascript使2个计数器背靠背运行



下面的函数自然会一次又一次地进入同一个循环。我想做的是从25秒开始倒计时,当它结束时,从10秒开始倒计数,然后回到25秒。但由于我在另一部分写的条件,它总是从10秒开始倒计时。我该怎么解决这个问题?

var interval = 25000;
var interval1 = 10000;
function millisToMinutesAndSeconds(millis) {
var seconds = ((millis % 60000) / 1000).toFixed(0);
return (seconds < 10 ? "0" : "") + seconds;
}
function tensecond() {
localStorage.endTime = +new Date() + interval1;
}
function reset() {
localStorage.endTime = +new Date() + interval;
}
setInterval(function () {
var remaining = localStorage.endTime - new Date();
if (remaining >= 0) {
document.getElementById("timer").innerText =
millisToMinutesAndSeconds(remaining);
} else {
tensecond();
}
}, 100);

一些评论:

  • 不要使用localStorage对象来存储您自己的属性。这与localStorage的目的无关。只需使用全局变量(如果您需要本地存储,则使用其getItemsetItem方法(

  • 不要使用toFixed(0)将数字四舍五入为整数。此外,将该字符串与10进行比较将进行基于字符的比较,而不是数字比较。相反,请使用Math.round,或此处更合适的Math.floor

  • 如果希望使用毫秒数而不是Date对象,请不要使用new Date()。请改用Date.now()

  • 不要对未初始化的值进行算术运算。在启动任何逻辑之前初始化endTime。因此,在调用setInterval()之前调用reset()

关于您的问题:

实现这一点的一种方法是制作一个循环,将两个间隔相加。然后在每个刻度处检查剩余时间是否在第一个或第二个间隔内。相应地调整显示的剩余时间。

以下是它的样子:

var interval = 25000;
var interval1 = 10000;
var endTime;
function millisToMinutesAndSeconds(millis) {
// Use floor instead of toFixed
var seconds = Math.floor((millis % 60000) / 1000);
return (seconds < 10 ? "0" : "") + seconds;
}
function reset() {
// Use Date.now() instead of +new Date()
// And create a cycle length that covers both intervals
endTime = Date.now() + interval + interval1;
}
reset();
setInterval(function () {
var remaining = endTime - Date.now();
if (remaining >= 0) {
// Adjust the time to display 
// depending on where in the total interval we are:
if (remaining >= interval1) remaining -= interval1;
document.getElementById("timer").innerText =
millisToMinutesAndSeconds(remaining);
} else {
reset()
}
}, 100);
<div id="timer"></div>

如果您只需要一个交替的倒计时计时器,就不需要包含特定的日期时间或本地存储。一种更简单的技术是只跟踪剩余的秒数,并在重复的1秒延迟后进行更新,每次从总数中减去一秒。

这里有一个例子(它还显示每一秒向上取整,而不是向下取整——所以它从25(或10(开始,并在达到0的确切时刻重置,而不是整秒钟显示0(:

const timerElement = document.getElementById('timer');
function updateTimerElement (seconds) {
timerElement.textContent = String(seconds).padStart(2, '0');
}
function delay (ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function countdown (seconds) {
while (seconds > 0) {
updateTimerElement(seconds);
await delay(1e3); // 1e3 is 1000 (1s)
seconds -= 1;
}
// You might want to update the timer one final time in order to show 0
// if you ever stop looping the countdowns:
// updateTimerElement(seconds);
}
async function main () {
// Store the total number of seconds for each countdown in order:
const secondsList = [25, 10];
// Keep track of the current one:
let listIndex = 0;
while (true) {
// Get the current number of seconds from the list:
const seconds = secondsList[listIndex];
// Run the countdown timer:
await countdown(seconds);
// Update the index to the next number of seconds in the list:
listIndex = (listIndex + 1) % secondsList.length;
}
}
main();
body { font-family: sans-serif; font-size: 4rem; }
<div id="timer"></div>

最后,请注意,JavaScript计时器不是精确的计时工具。查看更多信息:延迟超过指定时间的原因-setTimeout((-Web API|MDN

以下是事实:

  • (匿名(间隔函数第一次运行时,localStorage.endTime未初始化,因此值为undefined
  • undefined的任何算术运算都会导致NaN1,2,3,因此remaining被初始化为NaN
  • NaN(除了!=!==(的任何比较都是错误的4,5,6,因此间隔函数第一次运行时,它调用tensecond
  • 此后,间隔函数倒计时。当计时器用完时,它再次调用tensecond

短版本:永远不会调用reset

ECMAScript,第13版参考文献

  1. §13.15.3ApplyStringOrNumericBinaryOperator
  2. §7.1.4ToNumber
  3. §6.1.6.1.7Number::add ( x, y )
  4. §13.11.1运行时语义:评估
  5. §7.2.15IsLooselyEqual ( x, y )
  6. 6.1.6.1.13Number::equal

最新更新