How to Stop a Settimeout Loop

How to stop a setTimeout loop?

setTimeout returns a timer handle, which you can use to stop the timeout with clearTimeout.

So for instance:

function setBgPosition() {
var c = 0,
timer = 0;
var numbers = [0, -120, -240, -360, -480, -600, -720];
function run() {
Ext.get('common-spinner').setStyle('background-position', numbers[c++] + 'px 0px');
if (c >= numbers.length) {
c = 0;
}
timer = setTimeout(run, 200);
}
timer = setTimeout(run, 200);

return stop;

function stop() {
if (timer) {
clearTimeout(timer);
timer = 0;
}
}

So you'd use that as:

var stop = setBgPosition();
// ...later, when you're ready to stop...
stop();

Note that rather than having setBgPosition call itself again, I've just had it set c back to 0. Otherwise, this wouldn't work. Also note that I've used 0 as a handle value for when the timeout isn't pending; 0 isn't a valid return value from setTimeout so it makes a handy flag.

This is also one of the (few) places I think you'd be better off with setInterval rather than setTimeout. setInterval repeats. So:

function setBgPosition() {
var c = 0;
var numbers = [0, -120, -240, -360, -480, -600, -720];
function run() {
Ext.get('common-spinner').setStyle('background-position', numbers[c++] + 'px 0px');
if (c >= numbers.length) {
c = 0;
}
}
return setInterval(run, 200);
}

Used like this:

var timer = setBgPosition();
// ...later, when you're ready to stop...
clearInterval(timer);

All of the above notwithstanding, I'd want to find a way to make setBgPosition stop things itself, by detecting that some completion condition has been satisfied.

How to stop setTimeout loop if condition is met

You can't break the loop like that. Your loop creates all these setTimeout immediately. Your condition will just never trigger. What you'll need to do is clear out all those setTimeout. You can push them into an array.

let animationTimeouts;
function startScreensaver() {
animationTimeouts = [];
screensaverActive = true;
screenSaver.classList.add("is--active");
for (let index = 0; index < stars.length; index++) {
if (screensaverActive) {
animationTimeouts.push(setTimeout(function () {
stars[index].classList.add("is--visible");
}, 2000 * index));
} else {
break;
}
}
}

Then clear them out on stopScreensaver

  function stopScreensaver() {
screensaverActive = false;
if(animationTimeouts) animationTimeouts.forEach(clearTimeout);
stars.forEach((star) => {
star.classList.remove("is--visible");
});
screenSaver.classList.remove("is--active");
}

You might also want to reconsider moving your CSS transition to .star.is--visible

Stop loop function setTimeout

You can clear the timeout and also set a flag that will alert the callback in $.get that it shouldn't call timeOut() when it returns:

let i = 0;let sett;let active = true   // should the loop continue?function timeOut(counter) {      if (counter < 10){      sett = setTimeout(function () {        $.get("./test3.php", {data_id: counter}, (data) => {            console.log(data);            i++;            if (active) timeOut(i); // only if active        });      }, 1000);    } else {      alert("Done!");    }}timeOut(i);function clickStop() {    active = false      // stop loop    clearTimeout(sett); // and clear current timeout} 

Breaking out of setTimeout loop

Instead of setting all those timers, create one continuous timer with setInterval:

var counter = 0;

var timer = setInterval(function () {

console.log("turn no. " + counter);

if (table.game.playerWon) {
console.log('Player won');
}

if (counter >= 75 || table.game.playerWon) {
clearInterval(timer);
}

counter++;

}, 100);

If your turns should take 500ms, change that last 100 to 500.

Stop setTimeout loop, activated after click on button

This is exactly what you want (you can remove the console stmt after testing),

<script>
document.getElementById("addurls").onclick = function () {
var allurls = document.getElementById("allurls"); //$('#allurls').val().split('\n');
var urls = allurls.value.split('\n');
var el = document.getElementById("indexer");
var index = 0;

timer = setTimeout(function rotate() {

if (index === urls.length) {
clearTimeout(timer);
return true;
}

el.src = urls[index];
console.log("TEST: ", index);
index++;

timer = setTimeout(rotate, 2000);
}, 0);
};
</script>

Immediately stop a setTimeout loop without finishing current cycle

Your problem is in the flit() function - you need to assign references to the setTimeout calls so you can call clearTimeout on them. Right now, you're stopping flit() from being called in the select() method, but the two timers are still queued to execute in the future.

How to stop the setTimeout or setInterval inside loop?

How about you do it this way:

  1. Don't use a while loop because the while loop will call setTimeout many times and then you will have to clear ALL of them to pause. So it is simpler to not use the while loop
  2. When the function is called, let it set a timeout again after it is run.
  3. This means when toRepeat in my example below runs, it will create a timeout to run again so it runs the next step. Then it runs again and calls setTimeout again and so on until curStp is less than totalStps

Here is an example with comments, let me know if anything needs clarification.

let flag = 0;
const delay = 300;
const totalStps = 102;
var curStp = 0;
var timeout = null;

function toRepeat() {
let stp = curStp;
console.log("curStp = " + curStp);

curStp = stp+1; // this is done by setState.
console.log("flag " + flag + " timeout " + timeout);

// check for pause
if(flag === 1) {
console.log("break the loop");
console.log('clearing timeout = ', timeout);

// dont continue because we paused
return;
}

// each timeout will call another timeout again for the next step unless we already finished or we have paused
// better to have this `curStp < totalStps`
if(curStp != totalStps) {
// setup another timeout for next step
timeout = setTimeout(toRepeat, delay);
} else {
// we already finished
}
}

function mouseup() {
// need to set the flag back to 0 so pressing "Run Code" doesn't immediately pause again
flag = 0;

var timeout = setTimeout(toRepeat, delay);
}

function pause() {
flag = 1;
console.log("Value of flag in pause() " + flag + " curStp " + curStp);
let stp = curStp;
curStp = stp; // this is done by setState.
}

How to terminate endless while loop via setTimeout in Javascript

JavaScript runs a single event loop. It won't stop in the middle of a function to see if there are any events (such as clicks or timeouts) that would trigger a different function.

In short: It won't run the timed function until the while loop has finished.


To do this sort of thing, you'd normally have an event driven iterator.