0

I am trying to break the setTimeout function which is started on page load. So what I am doing here is, If I click on the button then I making flag value to true and setTimeout should break which isn't happening here. This setTimeout function is inside the for each loop. Below is my code.

                rData[0].dt.forEach(function(d, i) {
                    setTimeout(function() {
                        if(flag === "false"){
                            console.log(flag);
                            reserRadius(i); //here I am changing radius of circle
                        }else{
                            console.log(flag);
                            clearTimeout();
                            return;
                        }   

                    }, i * 2000);
                }); 
shanky
  • 751
  • 1
  • 16
  • 46
  • `clearTimeout` expects an id returned from `setTimeout`, but where you have it doesn't make sense, because by the time the function is evaluated the timeout is already completed and there is no reason to call `clearTimeout` – Rob M. Aug 11 '16 at 19:59
  • 4
    It is unclear what you exactly want your code to do. You cannot remove `timeout` inside itself, because when executed, it is already removed. It will be useful to post a [JSFiddle](https://jsfiddle.net/) snippet in your question. –  Aug 11 '16 at 20:04
  • I have animation code which is running inside this setTimeout function. I want this animation to stop if I hover over a particular region, so I am trying to stop it with the help of button. – shanky Aug 11 '16 at 20:08
  • @castis I have already tried assigning to a variable but still not able to break the loop. – shanky Aug 11 '16 at 20:10

2 Answers2

4

Instead of creating all timeouts in one go, only create them when needed. This way you don't have to clear any of them when you have determined to stop:

(function repeat(list, i) {
    if (i >= list.length) return; // nothing (more) to do 
    var d = list[i]; // do you need d at all??
    setTimeout(function() {
        if(flag === "false"){
            console.log(flag);
            reserRadius(i); //here I am changing radius of circle
            repeat(list, i+1); // schedule next timeout only now.
        }else{
            console.log(flag);
            // Don't schedule next timeout. This breaks the "loop".
        }   
    }, 2000); // trigger 2 seconds from now. Note: no multiplying anymore.
})(rData[0].dt, 0); // pass initial values: the array and index.

In your version of the code, you would have to keep the id values returned by all setTimeout calls, and then pass them all (or at the least the remaining ones) to clearTimeout, one by one. This would make your code quite cumbersome. I think the above is a more efficient approach.

trincot
  • 317,000
  • 35
  • 244
  • 286
0

setTimeout cannot be stopped from its callback itself. setTimeout returns a timeoutId which can be passed to clearTimeout which in turn will stop that particualr timer.

One way to stop all such timers is to create an array of timeoutIds and make changes as following.

var timerIds = [];
rData[0].dt.forEach(function(d, i) {
    timerIds.push(setTimeout(function(){
        if(flag === "false"){
            console.log(flag);
            reserRadius(i); //here I am changing radius of circle
        }
        else{
            console.log(flag);
        }
    }, i * 2000));
}); 

function stopTimeouts(){
    timerIds.forEach(function(id){
        clearTimeout(id);
    }
}
function codeThatMightChangeFlag(callback) {
    // do a bunch of stuff
    if (condition happens to change flag value) {
        // call the callback to notify other code
        stopTimeouts();
    }
}

Refer: Clear array of setTimeout's and Javascript - wait until flag=true

Community
  • 1
  • 1
Varun Singh
  • 310
  • 2
  • 10