Reputation: 75
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
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
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
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