倒计时项目中奇怪的 setInterval 问题

Posted

技术标签:

【中文标题】倒计时项目中奇怪的 setInterval 问题【英文标题】:Weird setInterval issue in a countdown project 【发布时间】:2022-01-23 04:16:21 【问题描述】:

我一边看教程一边写项目(比如,听我必须做的事情,然后自己做,看看我是否能成功)。这是代码:

const months = [
  "January",
  "February",
  "March",
  "April",
  "May",
  "June",
  "July",
  "August",
  "September",
  "October",
  "November",
  "December",
];
const weekdays = [
  "Sunday",
  "Monday",
  "Tuesday",
  "Wednesday",
  "Thursday",
  "Friday",
  "Saturday",
];

const deadline = document.querySelector(".deadline");
const giveaway = document.querySelector(".giveaway");
const h4 = document.querySelectorAll(".deadline-format h4");

let futureDate = new Date(2022, 4, 17, 11, 30, 0);

const yearTime = futureDate.getFullYear();
const monthTime = futureDate.getMonth();
const dayTime = futureDate.getDay();
const dateTime = futureDate.getDate();
const hourTime = futureDate.getHours();
const minutesTime = futureDate.getMinutes();

giveaway.innerhtml = ` Giveaway ends on $weekdays[dayTime], $dateTime $months[monthTime] $yearTime, $hourTime:$minutesTimeam`;

const futureTime = futureDate.getTime();
const currentTime = new Date().getTime();

let getRemainingTime = () => 

  const timeLeft = futureTime - currentTime;

  const oneDay = 24 * 60 * 60 * 1000;
  const oneHour = 60 * 60 * 1000;
  const oneMinute = 60 * 1000;
  const oneSecond = 1000;
  let days = Math.floor(timeLeft / oneDay);
  let hours = Math.floor((timeLeft % oneDay) / oneHour);
  let mins = Math.floor(((timeLeft % oneDay) % oneHour) / oneMinute);
  let secs = Math.floor(
    (((timeLeft % oneDay) % oneHour) % oneMinute) / oneSecond
  );
 
  const values = [days, hours, mins, secs];

  let zeroBefore = (item) => 
    if (item < 10) 
      return (item = `0$item`);
     else 
      return item;
    
  ;

  h4.forEach((item, index) => 
    item.innerHTML = zeroBefore(values[index]);
  );
;

// countdown
let countdown = setInterval(getRemainingTime, 1000);
//set initial values
getRemainingTime();

问题出现在函数开始之前:

const futureTime = futureDate.getTime();
const currentTime = currentDate.getTime();

let getRemainingTime = () => 
const timeLeft = futureTime - currentTime;

  const oneDay = 24 * 60 * 60 * 1000;
  const oneHour = 60 * 60 * 1000;
  const oneMinute = 60 * 1000;
  const oneSecond = 1000;
  let days = Math.floor(timeLeft / oneDay);
  let hours = Math.floor((timeLeft % oneDay) / oneHour);
  let mins = Math.floor(((timeLeft % oneDay) % oneHour) / oneMinute);
  let secs = Math.floor(
    (((timeLeft % oneDay) % oneHour) % oneMinute) / oneSecond
  );
  const values = [days, hours, mins, secs];

  let zeroBefore = (item) => 
    if (item < 10) 
      return (item = `0$item`);
     else 
      return item;
    
  ;

  h4.forEach((item, index) => 
    item.innerHTML = zeroBefore(values[index]);
  );

基本上,问题在于变量“currentTime”超出了函数范围,因此实时页面由于某种原因不会每秒更新一次。相反,如果我将“currentTime”放入函数中,它会突然起作用。为什么会这样?为什么我需要将变量“currentTime”放入函数中,而我不需要将变量“futureTime”放入函数中,它在我的函数中与“currentTime”的用法相同? 谢谢,如果我做错了什么对不起,这是我在这个网站上的第一篇文章!

【问题讨论】:

【参考方案1】:

我不确定我是否会形容你所看到的很奇怪。这对我来说似乎完全可以解释。

如果你在你的函数之外声明currentTime,即

const currentTime = new Date().getTime();

let getRemainingTime = () => 
  const timeLeft = futureTime - currentTime;
  ...
;

然后在您的脚本加载时评估一次currentTime。每次调用 getRemainingTime() 时,currentTime 的值都相同,因此您的代码似乎没有做任何事情,因为它每次运行时都会计算出相同的剩余时间。

另一方面,如果您在函数中声明 currentTime,即


let getRemainingTime = () => 
  const currentTime = new Date().getTime();
  const timeLeft = futureTime - currentTime;
  ...
;

然后每次调用您的函数时都会评估currentTime。每次调用它可能会有不同的值,因此它会在每种情况下计算不同的剩余时间。

您无需对futureTime 执行相同操作,因为该值不会改变。

请注意,在您的第二个代码块中,您引用了一个名为 currentDate 的变量,您没有在任何地方定义它。您的第一个代码块中的相应行使用 new Date() 代替,我假设这就是您的意思。

【讨论】:

哦,好吧,这就是问题所在!我认为只需使用 setInterval 再次重新加载代码就足以一次又一次地返回当前时间,但似乎我错了。非常感谢您的帮助!是的,我把贴在帖子上的第二个代码搞砸了,抱歉,我在帖子中做了一些更改。

以上是关于倒计时项目中奇怪的 setInterval 问题的主要内容,如果未能解决你的问题,请参考以下文章

Chrome开发者工具中奇怪的console.log行为[重复]

iOS 中奇怪的元素重叠 (PhoneGap)

iPhone 应用程序中奇怪的 OpenGL ES 行为

Bootstrap 中奇怪的 CSS 效果。在容器 div 内显示大量内容 div 时无意缩进

类中奇怪的异步/等待行为

Chrome 中奇怪的 CSS 边框问题