【问题标题】:Why is my date object returning back NaN values?为什么我的日期对象返回 NaN 值?
【发布时间】:2021-02-15 19:06:58
【问题描述】:

这是我的 JS 小提琴:

https://jsfiddle.net/apasric4/xkzwqr1m/1/

我的程序应该启动一个倒数计时器,计算从今天到用户在输入字段中选择的日期的剩余时间(以天、小时、秒等为单位)。

当程序用正确的剩余时间更新 HTML 时,当我尝试每秒更新倒数计时器时,问题就开始了。它出于某种原因返回 NaN 值。 为什么会这样??

这是我的 JS:

const input = document.querySelector('input')
let timeInterval;
let timeStop;


input.addEventListener('change', (e) => {
    e.preventDefault()
    timeStop = true;
    endTime = Date.parse(e.target.value)
    updateHTML(endTime)
})


function updateHTML(endTime) {
  let time = calculateTimeDiff(endTime)
  if (time.total <= 0) {
    timeStop = false;
  }
  for (let pro in time) {
    let el = document.querySelector(`.${pro}`)
    if (el) {
      el.innerHTML = time[pro];
    }
  }
  updateCounter();
}


function updateCounter () {
  if (timeStop) {
    timeInterval = setInterval(updateHTML, 1000);
  } else {
    clearInterval(timeInterval);
  }
}

//returning time remaining till date in object form 
function calculateTimeDiff(endTime) {
  let start = Date.now();
  let end = endTime;
  let t = (end-start);
  let seconds = Math.floor((t / 1000) % 60);
  let minutes = Math.floor((t / 1000 / 60) % 60);
  let hours = Math.floor((t / (1000 * 60 * 60)) % 24);
  let days = Math.floor(t / (1000 * 60 * 60 * 24));
  return {
    total: t,
    days: days,
    hours: hours,
    minutes: minutes,
    seconds: seconds
  }
}

【问题讨论】:

  • 这意味着您正在尝试使用无法理解的字符串创建 Date 实例。
  • 同时在区间回调中调用setInterval()再次会导致各种疯狂的问题。
  • timeInterval=setInterval(updateHTML, 1000) 。和function updateHTML (endTime) {。
  • setInterval(updateHTML 无参数调用updateHTML。 endTime 未定义。

标签: javascript setinterval countdowntimer clearinterval


【解决方案1】:

所以你的代码工作正常,但你的问题在于你的endTime。在您的setInterval 中,您在没有参数endTime 的情况下调用updateHTML,这样会导致错误,因为它没有对参数的引用。

您可以简单地更新您的 updateCounter 函数以接受它作为参数并将其传递给您的 setInterval 函数:

function updateCounter (endTime) {
  if (timeStop) {
    timeInterval=setInterval(() => updateHTML(endTime), 1000)
  } else {
    clearInterval(timeInterval)
  }
}

然后在 updateHtml 函数底部使用 endTime 调用 updateCounter。

或者,将endTime 作为参数从updateHtml 中移除,并使其成为全局变量:

const input=document.querySelector('input')
let timeInterval;
let timeStop;
let endTime;


input.addEventListener('change', (e)=> {
  e.preventDefault()
  timeStop=true;
  endTime=Date.parse(e.target.value)
  updateHTML()
})


function updateHTML () {
  let time=calculateTimeDiff(endTime)
  if (time.total<=0) {
    timeStop=false
  }
  for (let pro in time) {
    let el=document.querySelector(`.${pro}`)
    if (el) {
      el.innerHTML=time[pro]
    }
  }
  updateCounter()
}


etc...

【讨论】:

    【解决方案2】:

    当更新从事件发生时 - 一切都很好

    但后来你使用timeInterval=setInterval(updateHTML, 1000) - 和updateHTML 在没有参数的情况下执行。改为使用真实日期,它会起作用

    工作示例:

    const input = document.querySelector('input')
    let timeInterval;
    let timeStop;
    let savedTime;
    
    input.addEventListener('change', (e) => {
      e.preventDefault()
      timeStop = true;
      endTime = Date.parse(e.target.value)
      updateHTML(endTime)
    })
    
    function updateHTML(endTime) {
      savedTime = endTime || savedTime;
      let time = calculateTimeDiff(savedTime)
      if (time.total <= 0) {
        timeStop = false
      }
      for (let pro in time) {
        let el = document.querySelector(`.${pro}`)
        if (el) {
          el.innerHTML = time[pro]
        }
      }
      updateCounter()
    }
    
    function updateCounter() {
      if (timeStop) {
        timeInterval = setInterval(updateHTML, 1000)
      } else {
        clearInterval(timeInterval)
      }
    }
    
    //returning time remaining till date in object form 
    function calculateTimeDiff(endTime) {
      let start = Date.now()
      let end = endTime
      let t = (end - start)
      let seconds = Math.floor((t / 1000) % 60);
      let minutes = Math.floor((t / 1000 / 60) % 60);
      let hours = Math.floor((t / (1000 * 60 * 60)) % 24);
      let days = Math.floor(t / (1000 * 60 * 60 * 24));
      return {
        total: t,
        days: days,
        hours: hours,
        minutes: minutes,
        seconds: seconds
      }
    }
    .time {
      display: inline-block;
      border-radius: 25%;
    }
    <!DOCTYPE html>
    
    <head>
      <meta charset="utf-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <title></title>
      <meta name="description" content="">
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <link rel="stylesheet" href="styles.css">
    </head>
    
    <body>
    
      <input type="date" name="endDate">
      <div class="clock">
        <div class="time"><span class="days">0</span> Days</div>
        <div class="time"><span class="hours">0</span> Hours</div>
        <div class="time"><span class="minutes">0</span> Minutes</div>
        <div class="time"><span class="seconds">0</span> Seconds</div>
      </div>
    
    
    </body>
    
    <script src="app.js"></script>
    
    </html>

    【讨论】:

    • 为什么需要创建新变量 savedTime?为什么当我们每秒调用它时,我们不必在 updateHTML 中放置一个参数?
    • 您可以这样做,但您必须从某个地方获取它。在您的情况下,您仅在从事件执行时第一次在参数中使用日期。但是所有超时调用都没有事件,也不知道去哪里取日期
    • 嘿,这行得通。但我也注意到倒数计时器不会按秒倒计时。它的滴答声比那更快。你知道这是为什么吗?
    【解决方案3】:

    试试这个....

    const input=document.querySelector('input')
    let timeInterval;
    let timeStop;
    let endTime;
    
    input.addEventListener('change', (e)=> {
      e.preventDefault()
      timeStop=true;
      endTime=Date.parse(e.target.value)
      updateHTML()
    })
    
    
    function updateHTML () {
      let time=calculateTimeDiff()
      if (time.total<=0) {
        timeStop=false
      }
      for (let pro in time) {
        let el=document.querySelector(`.${pro}`)
        if (el) {
          el.innerHTML=time[pro]
        }
      }
      updateCounter()
    }
    
    
    function updateCounter () {
      if (timeStop) {
        timeInterval=setInterval(updateHTML(), 1000)
      } else {
        clearInterval(timeInterval)
      }
    }
    
    //returning time remaining till date in object form 
    function calculateTimeDiff () {
      let start=Date.now()
      let end=endTime
      let t=(end-start)
      let seconds = Math.floor((t / 1000) % 60);
      let minutes = Math.floor((t / 1000 / 60) % 60);
      let hours = Math.floor((t / (1000 * 60 * 60)) % 24);
      let days = Math.floor(t / (1000 * 60 * 60 * 24));
      return {
        total: t,
        days: days,
        hours: hours,
        minutes: minutes,
        seconds: seconds
      }
    }
    

    【讨论】:

    • 嘿,我认为代码格式不正确?
    • 嘿,为什么它说我的代码超出了最大调用堆栈?
    • sry,尝试不将 endTime 作为参数发送给任何函数作为其全局
    • 对不起,我不明白你的意思?你想让我不要将 endTime 设置为全局吗?你能更新你的代码,这样我就知道你想说什么了吗?
    • 嘿,这行得通。但我也注意到倒数计时器不会按秒倒计时。它的滴答声比那更快。你知道这是为什么吗?
    【解决方案4】:

    只需在代码中的函数 updateCounter() 中添加 preventDefault() 即可。 希望它会奏效。我试过了,它成功了。

    【讨论】:

      猜你喜欢
      • 2016-08-03
      • 1970-01-01
      • 2015-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-10
      • 2013-08-06
      相关资源
      最近更新 更多