1

I am trying to make a Countdown that just log in the terminal the seconds remaining. It should be an interval of 1 second between every log. It has to be as a method of an object. I don´t know if it's because of the scope but somehow it's not working after many trials and code-rewriting.

Anybody can help me with this?

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

3 Answers3

1

I would use a setInterval() for a simple countdown timer. I would also write my function for the math loop outside of the setInterval and then call on the function within the interval, like the following => setInterval(timerFunction(), 1000). There is no need for a loop when you use the interval, it does the looping each defined time increment as set in your setInterval(). Each time the interval fires, the function will do its thing.

EDIT: added a conditional to see if the interval time has run out.

I have included an example of a simple count down timer in my answer below along with notation inside the code that helps to explain further. Hope this helps.

Also, by terminal, I assume you mean the console? My example displays the setInterval in the console...

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;
  
}
dale landry
  • 7,831
  • 2
  • 16
  • 28
1

Yes it was because of the scope. As you are using this inside setTimeout() it uses the global scope.

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)
    }
}

I'm using bind to set "this" to current context.

And with reference to your question about timeout, instead of using setTimeout() use setInterval() to achieve your need about log with respect to seconds

Sam
  • 572
  • 3
  • 11
1

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>
The Bomb Squad
  • 4,192
  • 1
  • 9
  • 17