In the top answer, I think the if (timer)
statement has been mistakenly placed within the stop()
function call. It should instead be placed within the run()
function call like if (timer) timer = setTimeout(run, 200)
. This prevents future setTimeout
statements from being run right after stop()
is called.
EDIT 2: The top answer is CORRECT for synchronous function calls. If you want to make async function calls, then use mine instead.
Given below is an example with what I think is the correct way (feel to correct me if I am wrong since I haven't yet tested this):
const runSetTimeoutsAtIntervals = () => {
const timeout = 1000 // setTimeout interval
let runFutureSetTimeouts // Flag that is set based on which cycle continues or ends
const runTimeout = async() => {
await asyncCall() // Now even if stopRunSetTimeoutsAtIntervals() is called while this is running, the cycle will stop
if (runFutureSetTimeouts) runFutureSetTimeouts = setTimeout(runTimeout, timeout)
}
const stopRunSetTimeoutsAtIntervals = () => {
clearTimeout(runFutureSetTimeouts)
runFutureSetTimeouts = false
}
runFutureSetTimeouts = setTimeout(runTimeout, timeout) // Set flag to true and start the cycle
return stopRunSetTimeoutsAtIntervals
}
// You would use the above function like follows.
const stopRunSetTimeoutsAtIntervals = runSetTimeoutsAtIntervals() // Start cycle
stopRunSetTimeoutsAtIntervals() // Stop cycle
EDIT 1: This has been tested and works as expected.