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

Weird setInterval issue in a countdown project

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

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}:${minutesTime}am`;

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”的用法相同? 谢谢,抱歉,如果我做错了什么,那是我第一次 post 在这个网站上!

我不确定我是否会将您所看到的描述为奇怪的。这对我来说似乎完全可以解释。

如果您在函数外声明 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() 代替,我假设这就是您的意思。