0

So I developed a countdown function, in the code below I test it with a 1 minute input, but the console throws all the values at once. What should happen is a number every second, I believe the problem is that setTimeout is probably not working, but how to fix?

 function countdown(tempominutos) {
    let tempo = new Date();
    tempo.setHours(0, tempominutos, 0);
    let tempoformatado = tempo.toLocaleTimeString();
    console.log(tempoformatado);
    while ((tempo.getSeconds() > 0) || (tempo.getMinutes() > 0) || (tempo.getHours() > 0)) {
      tempo.setSeconds(tempo.getSeconds() - 1);
      tempoformatado = tempo.toLocaleTimeString();
      setTimeout(console.log(tempoformatado), 1000);
    }
  }
  countdown(1);
dev-math
  • 3
  • 1
  • 3
    setTimeout doesn't block function execution, but only schedules some work for later – Max Jan 12 '20 at 02:24
  • The console.log within setTimeout runs, but instantly. It does not wait for the programmed 1 second (1000 ms). – dev-math Jan 12 '20 at 02:27

2 Answers2

0

There are several problems in your code:

Firstly, setTimeout's first argument is a function, you're providing console.log(tempoformatado) which will execute console.log and evaluate to undefined.

You can solve this by wrapping your statement with a function:

setTimeout(function() { console.log(tempoformatado) }, 1000);

Secondly, you are using the same timeout for all your callbacks. You need to keep in mind that your while loop is executing instantly. All timeouts will have finished at the exact same time and almost 1000ms after the initial tempoformatado log.

To counter that you need to make the interval dependent to the time you're showing. For example you could calculate 1000ms times the number of seconds:

1000*tempo.getSeconds()

Finally, you need to make tempoformatado local to the while block. This makes sure that each loop as its own value of tempoformatado. You can do this by redefining tempoformatado with the let keyword inside the while loop

function countdown(tempominutos) {
  let tempo = new Date();
  tempo.setHours(0, tempominutos, 0);
  let tempoformatado = tempo.toLocaleTimeString();
  console.log(tempoformatado);
  while ((tempo.getSeconds() > 0) || (tempo.getMinutes() > 0) || (tempo.getHours() > 0)) {
    tempo.setSeconds(tempo.getSeconds() - 1);
    let tempoformatado = tempo.toLocaleTimeString();
    setTimeout(function() {
      console.log(tempoformatado)
    }, 1000*tempo.getSeconds());
  }
}
countdown(1);
Ivan
  • 34,531
  • 8
  • 55
  • 100
  • I ended up finding another problem with the code, but the setTimeout problem was solved. I will study what you said until you understand. Thanks a lot for the help! – dev-math Jan 12 '20 at 02:48
0

Your code expects setTimeout to work like a sleep function.

Instead, replace it with the sleep function defined here: https://stackoverflow.com/a/39914235/6801443

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function countdown(tempominutos) {
  let tempo = new Date();
  tempo.setHours(0, tempominutos, 0);
  let tempoformatado = tempo.toLocaleTimeString();
  console.log(tempoformatado);
  while ((tempo.getSeconds() > 0) || (tempo.getMinutes() > 0) || (tempo.getHours() > 0)) {
    tempo.setSeconds(tempo.getSeconds() - 1);
    await sleep(1000);
    tempoformatado = tempo.toLocaleTimeString();
    console.log(tempoformatado);
  }
}
countdown(1);
Sean F
  • 4,344
  • 16
  • 30