使用 JavaScript 创建倒计时

Creating a Countdown with JavaScript

我正在尝试制作一个倒计时,只在剩余秒数时登录终端。每条日志之间应该间隔 1 秒。它必须作为对象的方法。我不知道是不是因为范围的原因,但不知何故,经过多次试验和代码重写后它无法正常工作。

有人可以帮我解决这个问题吗?

var Countdown = function(seconds) {
    this.counter = seconds;
    this.start = function() {
        setTimeout(
            function() {
                while (this.counter >= 0) {
                    console.log(this.counter);
                    this.counter -= 1;
                }
            },1000)
    }
}

我会使用 setInterval() 作为简单的倒数计时器。我还会在 setInterval 之外为数学循环编写我的函数,然后在间隔内调用该函数,如下所示 => setInterval(timerFunction(), 1000)。使用间隔时不需要循环,它会按照 setInterval() 中设置的每个定义的时间增量进行循环。每次触发间隔时,函数都会执行它的操作。

编辑: 添加了一个条件来查看间隔时间是否有运行。

我在下面的回答中包含了一个简单的倒数计时器示例,以及有助于进一步解释的代码中的符号。希望这有帮助。

此外,对于终端,我假设您指的是控制台?我的示例在控制台中显示了 setInterval...

let sMin = 2; // amount of minutes you wish to start with
let time = sMin * 60; // format for minutes by multiplying by 60 as we have 60 seconds in each minute

let countdown = setInterval(update, 1000) // set up a setInterval for the countdown function
// create a function that will countdown the seconds
function update() {
  // define our minutes using Math.floor(time / 60)
  let min = Math.floor(time / 60);
  // define our seconds by modulating time with 60, our seconds units
  let sec = time % 60;
  
  // tenerary conditional to see if seconds is set to 0 for proper display of formatting as seconds 
  sec = sec < 10 ? '0' + sec : sec;
  // display the countdown timer in time format using the minutes and seconds variables
  console.log(`${min}:${sec}`);
  // decrement time by one second with each interval as set in the setInterval call `1000`
  time--;
  // clear the interval if the minutes and seconds are both set to 0
  min == 0 && sec == 0 ? clearInterval(countdown) : countdown;
  
}

是的,这是因为范围。当您在 setTimeout() 中使用它时,它使用全局范围。

var Countdown = function(seconds) {
    this.counter = seconds;
    this.start = function() {
        setTimeout(
            function() {
                while (this.counter >= 0) {
                    console.log(this.counter);
                    this.counter -= 1;
                }
            }.bind(this),1000)
    }
}

我正在使用绑定将“this”设置为当前上下文。

关于你关于超时的问题,而不是使用 setTimeout() 使用 setInterval() 来实现你对日志的秒数需求

function countDown(whileCountingDown, forHowLong, whenFinishedThen){
  //error handling begin(for user's understanding)
  if(arguments.length<3){return RangeError("ALL three arguments must be used")}
  var typeErrors=[]
  if(typeof whileCountingDown!="function"){typeErrors.push("whileCountingDown MUST be a function")}
  if(typeof forHowLong!="number"){typeErrors.push("forHowLong MUST be a number(and it represents seconds)")}
  if(typeof whenFinishedThen!="function"){typeErrors.push("whenFinishedThen MUST be a function")}
  if(typeErrors.length>0){return TypeError(`There are ${typeErrors.length} parameters that are incorrect data types\n\n${typeErrors.join('\n')}`)}
  //error handling begin(for user's understanding)
  
  //........................................................................................................................
  //the part that matters to you once you enter correct stuff
  var i=setInterval(()=>{forHowLong--
    if(forHowLong<=0){//count finished, determine what happens next
      clearInterval(i); whenFinishedThen()
    }
    else{whileCountingDown(forHowLong)}//do this for each second of countdown
  },1000)
}
console.log("The timers in the console and on the html element are 2 DIFFERENT countdowns")
//example use
countDown((m)=>{console.log(`${m} seconds left`)}, 30, ()=>{console.log('Cheers, the countdown is OVER')})





//obviously you can do stuff like edit randomHTML-Element.innerText for each second of the countdown or anything as you so desire since what i made is kindof flexible
//..........................................................................................................................




//more examples
//now for some fun stuff, we're gonna be editing an html structure, but first, we're going to make a 'timeParse' function to make it look kind of elegant
function timeParse(seconds){
  //yup, error handling begin
  if(typeof seconds!="number"){return TypeError("The parameter 'seconds' MUST be a number")}
  //yup, error handling end
  
  //below is the stuff to look at
  var timeArr=[seconds]
  if(timeArr[0]>=60){//if seconds >= 1 minute
    timeArr.unshift(Math.floor(timeArr[0]/60))
    timeArr[1]=timeArr[1]%60
    
    if(timeArr[0]>=60){//if minutes >= 1 hour
      timeArr.unshift(Math.floor(timeArr[0]/60))
      timeArr[1]=timeArr[1]%60
      
      if(timeArr[0]>=24){//if hours >= 1 day
        timeArr.unshift(`${Math.floor(timeArr[0]/24)}d`)
        timeArr[1]=timeArr[1]%24
      }
    }
  }
  return(timeArr.join`:`)
}
//now for applying countDown to things other than the console
function countDownAgain(){//just something that will show the flexibility of what i made.. im going above and beyond because i wanna look back on my answers as notes on how to do things(also ez copy pasting for future me xD)
  countDown(
    (s)=>{document.getElementById('toTime').innerText="Second Count "+timeParse(s)},
    86401,
    ()=>{document.getElementById('toTime').innerText="No way you waited that long LOL"}
  )
}
countDown(
  (s)=>{document.getElementById('toTime').innerText="First Count "+timeParse(s)},
  100,
  countDownAgain
)
<div style="background-color:red;height:100px;text-align:center;line-height:50px"><h1 id="toTime">Count Down Time :}</h1></div>