0

I am new to JavaScript and was learning about promises. I want to print 5 to 0 numbers at the interval of 2 seconds each. For example for the first time after 2 seconds print 5 and then after 2 second print 4 and so on. I have written a code to do so but not able to get the correct output.

var count = 5;
var i = 2;
function d()                     
{
    let p = new Promise((resolve,reject)=>{
        while(count>=0)
        {
            setTimeout(resolve,i*1000,count);
            i= i*2;
            count = count-1;
            //count = count-1;
        }
    });
    return p;
}

d().then((x)=>{
    console.log(x);
});

It is showing output as 5. Can anyone correct it?

Hash Blog
  • 19
  • 2
  • 1
    You are calling resolve `count` times, but a promise can only be resolved or rejected once. You have to create five distinct promises and await all of them. – derpirscher Feb 28 '22 at 07:55
  • Furthermore youd `count` is global. Thus, when you call resolve, it will get this global count (which is 5 after the loop) as parameter – derpirscher Feb 28 '22 at 07:58
  • @derpirscher Can u explain what do I need to change? – Hash Blog Feb 28 '22 at 08:03
  • Does this answer your question? [JS: How to have a Promise with a timeout in a loop?](https://stackoverflow.com/questions/65429264/js-how-to-have-a-promise-with-a-timeout-in-a-loop) – derpirscher Feb 28 '22 at 08:14

2 Answers2

1

It's much easier to write this using the async ... await syntax... you can then create a pause function that will delay by timeout milliseconds. We can wrap this in a while statement, looping until the count is zero.

async function pause(timeout) {
    return new Promise(resolve => setTimeout(resolve, timeout))
}

async function countDown(count) {
    while (count > 0) {
        await pause(2000);
        console.log('count:', count);
        count--;
    }
}

countDown(5);
Terry Lennox
  • 29,471
  • 5
  • 28
  • 40
0

Whenever you are writing a program, it is a good idea to quantify what it is you need to keep track of.

In this case we have three components.

  1. We want to do something on each "tick", and we want to know what "tick" we are on.
  2. We want to count down from a specific number until we are at 0.
  3. Each "tick" should be separated by a set amount of time.

A basic for..loop let's us loop over the number range and queue up some setTimeout calls with our callback:

/**
 * CountDown
 *
 * @param {Function} callback - The callback is a function that we call each "tick"
 * @param {number} countDownFrom - The countdown starts at this number
 * @param {number} interval - the number of milliseconds between each "tick"
 */
function CountDown(
  callback,
  countDownFrom,
  interval
) {
  for (var count = 0; count <= countDownFrom; count++) {
    setTimeout(callback, (countDownFrom - count) * interval, count);
  }
}
CountDown(
  (x) => {
    console.log(x);
  },
  5,
  2 * 1000
);

I have put some links to www.w3schools.com in this answer. There you can find documentation and tutorials for a lot of JavaScript problems.

Emil S. Jørgensen
  • 6,216
  • 1
  • 15
  • 28