First of all, declare let b = true
outside of the callback function. It's re-initialized on each call otherwise.
Secondly, the 10000 in clearTimeout(fnInterval, 10000)
isn't a valid parameter. clearTimeout(timeoutId)
accepts only the first parameter and clears the timeout passed in immediately. You'd need a setTimeout
to trigger this after 10 seconds, if that's your goal. But that causes a race condition between the two timeouts -- imprecision can mean you'll miss some of the logs or wind up with extra logs.
Using a counter is one solution, as other answers show, but usually when I'm using complex timing with setInterval
that requires clearing it after some number of iterations, I refactor to a generic promisified sleep
function based on setTimeout
. This keeps the calling code much cleaner (no callbacks) and avoids messing with clearTimeout
.
Instead of a boolean to flip a flag back and forth between two messages, a better solution is to use an array and modulus the current index by the messages array length. This makes it much easier to add more items to cycle through and the code is easier to understand since the state is implicit in the counter.
const sleep = ms => new Promise(res => setInterval(res, ms));
(async () => {
const messages = ["hi", "bye"];
for (let i = 0; i < 10; i++) {
console.log(messages[i%messages.length]);
await sleep(1000);
}
})();