3

I'm trying to provide a pause and resume functionality to a loop with recursive calls. I'm using "setTimeout" and "clearTimeout" functions for this...

When a user clicks the button "pause", the timer is set to infinite time (maximum possible). When the user clicks the button "resume", the timeout is supposed to be cleared with "clearTimeout" call. But the timeout is never cleared. What is my mistake?

Thank you in advance..

JFIDDLE DEMO

HTML:

<button id="loop_controler">pause</button>

JS:

var array = [1,2,3,4,5,6,7];
var pause = false;
var timer;

function execute(array,i){
    var pauseTime = 0;
    if (pause){
        pauseTime = 2147483647;  //max value for timeout     
    }
    timer = setTimeout(function(){        //set timer
           setTimeout(function () {       
               alert(array[i]);           //this timeout gives a constant delay
               if (array.length > i)      //(just to give enough time to users to click button)
                   execute(array,i+1);
           }, 1000);
    }, pauseTime);
    console.log('set ' + timer);
}

$('document').ready(function(){

    $('#loop_controler').click(function(){
        if ($(this).text() == 'pause'){
          pause = true;
          $(this).text('resume');
        } else {
          clearTimeout(timer);           //clear timer
          console.log('clear ' + timer);
          pause = false;
          $(this).text('pause');
        }
    });

    execute(array,0);
});
Sampath Liyanage
  • 4,776
  • 2
  • 28
  • 40
  • Why don't you clear the timeout when the user clicks Pause, instead of setting the timeout to infinity? And then start it again when the user clicks resume. – Barmar Nov 02 '14 at 06:44
  • The main problem is that after you clear the timeout, you're not restarting it with a normal timeout. – Barmar Nov 02 '14 at 06:45
  • You need `i` to be a global variable, so you can restart the timer at the current position in the array. – Barmar Nov 02 '14 at 06:46
  • See this similar answer I gave earlier tonight: http://stackoverflow.com/questions/26695911/pause-resume-settimeout-in-a-loop/26696040#26696040 – Barmar Nov 02 '14 at 06:47
  • I was misunderstanding the clearTimeout function. I thought the callback would be executed immediately after we clear the timeout... Thank you a lot for your help.. – Sampath Liyanage Nov 02 '14 at 07:41

2 Answers2

7

Back in 2012 I wrote a snippet of code for delta timing in JavaScript, which uses setTimeout and has start and stop functions: https://gist.github.com/aaditmshah/2056987

See the demo:

var button = document.querySelector("button");
var div = document.querySelector("div");

var running = false;

var number = 1;

var timer = new DeltaTimer(function () {
  div.innerHTML = number++;
}, 1000);

button.addEventListener("click", function () {
  if (running) {
    timer.stop();
    button.innerHTML = "Start";
    running = false;
  } else {
    timer.start();
    button.innerHTML = "Stop";
    running = true;
  }
});

function DeltaTimer(render, interval) {
    var timeout;
    var lastTime;

    this.start = start;
    this.stop = stop;

    function start() {
        timeout = setTimeout(loop, 0);
        lastTime = Date.now();
        return lastTime;
    }

    function stop() {
        clearTimeout(timeout);
        return lastTime;
    }

    function loop() {
        var thisTime = Date.now();
        var deltaTime = thisTime - lastTime;
        var delay = Math.max(interval - deltaTime, 0);
        timeout = setTimeout(loop, delay);
        lastTime = thisTime + delay;
        render(thisTime);
    }
}
<button>Start</button>
<div></div>

Hope that helps.

Aadit M Shah
  • 72,912
  • 30
  • 168
  • 299
2

I was misunderstanding the clearTimeout function. I thought the callback (calback in setTimeout(...)) would be executed immediately after clearTimeout is called. But the callback is not executed after clearTimeout is called...

The working JS code is,

var array = [1,2,3,4,5,6,7];
var timer;
var i=0;

function execute(){
     timer = setTimeout(function () {
               alert(array[i]);
               i++;
               if (array.length > i){
                   execute();
               }
           }, 1000);
}

$('document').ready(function(){

    $('#loop_controler').click(function(){
        if ($(this).text() == 'pause'){
          clearTimeout(timer);
          $(this).text('resume');
        } else {
          execute();
          $(this).text('pause');
        }
    });

    execute(array,0);
});
Sampath Liyanage
  • 4,776
  • 2
  • 28
  • 40