Katherine Chen
Katherine Chen

Reputation: 75

How to wrap consecutive setInterval() in a forever loop?

I was trying to implement a function, which is supposed to post measurement A every 5 sec for 10 times, and then post measurement B every 5 sec for a random amounts of time. And I want repeat this function forever as I was trying to implement a fake agent.

So I had the code:

let intervalId = null, repeat = 0;
while (true) {
    intervalId = setInterval(() => {
      if (repeat < 5) {
        // post measurement A
        repeat += 1;
      }
      else {
        clearInterval(intervalId)
      }
    }, 1000);

    repeat = 0;
    intervalId = setInterval(() => {
      if (repeat < Math.floor(Math.random() * 11)) {
        // post measurement B
        repeat += 1;
      }
      else {
        clearInterval(intervalId)
      }
    }, 1000);
}

The two setInterval() function didn't happen consecutively as I expected, instead they happened at the same time. And the while (true) loop seems not behave as expected either. I'm just wondering is there any way to get around with this problem? Thanks.

Upvotes: 3

Views: 1383

Answers (3)

Cuong Vu
Cuong Vu

Reputation: 3723

You can create two function, one is doA() and one is doB().

Start with doA(), count the number of time //do A is called, when it reached 10, clearInterval and call doB().

In doB(), set the min and max time it should be called, then when it reached randTime clearInterval and doA()

function doA() {

  let count = 0;
  const a = setInterval(() => {
    //do A
    console.log('do A');
    count += 1;
    if (count === 10) {
      clearInterval(a);
      doB();
    }
  }, 5000/10);

}
function doB() {
  // set your min and max for B
  const minTime = 1;
  const maxTime = 10;
  const randTime = Math.floor(Math.random() * (maxTime - minTime + 1)) + minTime;
  let count = 0;
  const b = setInterval(() => {
    // do B
    console.log(randTime);
    console.log('do B');
    count += 1;
    if (count === randTime) {
      clearInterval(b);
      doA();
    }
  }, 5000 / randTime);
}
doA();

Upvotes: 1

kiddorails
kiddorails

Reputation: 13014

Working on top of your code, first thing first, remove infinite while loop. It will run endlessly in synchronous fashion while setInterval is asynchronous. repeat value will be far ahead before you do repeat += 1.

Second, break them down in function so they have their own closure for intervalId and repeat value.

function intervalA () {
  let intervalId = null
  let repeat = 0
  intervalId = setInterval(() => {
    if (repeat < 5) {
      console.log(new Date(), 'A')
      // post measurement A
      repeat += 1; // increment repeat in callback. 
    }
    else {
      clearInterval(intervalId); // done with interval, clear the interval
      intervalB(); // and start interval B
    }
  }, 1000)
}

function intervalB () {
  let repeat = 0
  let randomEnd = Math.floor(Math.random() * 11) // calculate when it should end.
  let intervalId = setInterval(() => {
    if (repeat < randomEnd) {
      console.log(new Date(), 'B will finish in', randomEnd, 'times') 
      repeat += 1
    }
    else {
      clearInterval(intervalId) // clear the interval once done
    }
  }, 1000)
}

intervalA(); //start with interval A

Upvotes: 1

CertainPerformance
CertainPerformance

Reputation: 370689

Currently, the intervals are being set at once, synchronously, at the start of your script and during every while thereafter. It would probably be clearer if you only a single interval, with a variable that indicated which measurement to run, and change that variable every random-nth iteration:

const getRandomRepeats = () => Math.ceil(Math.random() * 11)
let repeatsRemaining = getRandomRepeats();;
let measureA = true;
setInterval(() => {
  repeatsRemaining--;
  if (repeatsRemaining === 0) {
    repeatsRemaining = getRandomRepeats();
    measureA = !measureA;
  }
  console.log('repeats remaining: ' + repeatsRemaining);
  if (measureA) {
    console.log('posting a');
  } else {
    console.log('posting b');
  }
}, 1000);

Upvotes: 0

Related Questions