Akimbo
Akimbo

Reputation: 61

Why does awaiting a setInterval promise inside of a while loop cause the amount of calls to stack up?

I was just trying to make a simple async function that runs on a schedule. I was just starting off with a counter. But this loop is behaving differently from how I imagined.

async function runCheckChats(){
  while(true){
    count++
    console.log(`this loop is running`);
    await new Promise(res => {
      setInterval(() => {
        count++
        res(3);
      }, 3000)
    })

    console.log(`count = ${count}`)

  }
}

runCheckChats();

The first time the loop runs, count is increased by one. The second time, it's increased by two, and so on. Why is this happening? When we await a promise, wouldn't we be exiting runCheckChats in the event loop? Why does it seem like the while keeps going instead of waiting? I would expect it to count every 3 seconds.

Upvotes: 0

Views: 419

Answers (1)

Nicholas Tower
Nicholas Tower

Reputation: 85152

Intervals fire repeatedly, and you're creating more and more intervals.

You start off by creating an interval, and after 3 seconds it fires, increments count, and resolves the promise. Since the promise has resolved, you repeat your loop and create an additional interval. After 3 more seconds, both of the intervals go off. They each increment count, and each resolve their corresponding promise (one of them is already resolved, so that does nothing). And then repeat again, now with 3 intervals.

If you want to keep the code roughly the same way it is now, use a timeout instead of an interval. Timeouts only go off once, so when one ends you can safely create another without they piling up.

setTimeout(() => {
  count++
  res(3);
}, 3000)

Alternatively you could rework the code to use just a single interval, but in that case promises won't be a good fit, since promises can only resolve once.

function runCheckChats() {
  setInterval(() => {
    count++;
    console.log(`count = ${count}`)
  }, 3000);
}

Upvotes: 4

Related Questions