Will clearInterval stop queued interval execution
Asked Answered
R

1

5

Let's say I have these this

myInterval=setInterval(funcA,50);

function funcA(){
  //Some code that takes longer than 50ms to run
}

setTimeout(function(){clearInterval(myInterval);},10000}

Let's say funcA always takes longer than 50ms to make it simple. Naturally, many funcA runs will pile up and be queued. Will clearInterval remove those queued runs or just stop queuing new ones?

I did make a fiddle to test it, and it turns out clearInterval stops all future execution, even those that have already be queued. I just need to confirm this behavior is consistent (across browsers/platforms).

var myInterval=setInterval(funcA,20);

setTimeout(function(){
  clearInterval(myInterval);
  
  console.log('Clearing interval at ' + Date.now());
  
},400);

var lastRunTimeStamp=0;

function funcA(){
  while(Date.now()<lastRunTimeStamp+25){}
  lastRunTimeStamp=Date.now();
  console.log('Run at ' + lastRunTimeStamp);
}

--Update--

The queued execution assumption in this question is incorrect, please check T.J. Crowder answer for an explanation.

Rabinowitz answered 13/11, 2017 at 11:49 Comment(1)
Bonus question: any idea why this behavior is not clearly documented (at least where I looked)?Rabinowitz
J
10

Naturally, many funcA runs will pile up and be queued.

No, they won't, because of the way the repeated timer works. Timer behavior in browsers is (now) specified by the WHAT-WG "HTML5" specification. Queuing the next task is done as part of the previous task, after your callback has completed, not separately from it; details here. So there will only be one outstanding task at a time (after it's been queued, before the JavaScript engine can pick it up and work on it).

Will clearInterval remove those queued runs or just stop queuing new ones?

No*, but it doesn't have to. The first step in the task queued by the timer system is to see if the timer is still on the list of active timers; if it isn't, the task terminates before calling your callback. So it's as though clearInterval removed the task (e.g., your formerly-queued callback doesn't get run), but not because clearInterval cleared it (instead, it's because the task checked).

It's easy to test and prove the behavior: Just schedule a timer, then busy-wait for longer than its interval, then clear it:

var counter = 0;
var timer = setInterval(function() {
  ++counter;
  console.log("timer fired:", counter);
  if (counter == 1) {
    setTimeout(busyWaitAndClear, 0);
  }
}, 500); // Every 500ms
function busyWaitAndClear() { // Obviously never really do this
  var done = Date.now() + 1000;
  while (done > Date.now()) {
    // wait
  }
  clearInterval(timer);
  console.log("timer cleared");
}

Note that the timer only fires once, and doesn't fire a second time even though presumably at least one task to fire it was queued while we busy-waited.


* ("No" - The description of clearInterval doesn't say anything about reading into the pending tasks list and removing tasks queued by the interval but not yet picked up.)

Jaggery answered 13/11, 2017 at 11:55 Comment(7)
Interesting. What's the procedure here (for a question based on a wrong premise)? Should I fix it somehow, or even remove it?Rabinowitz
@RSinohara: Others may well also have the wrong assumption, so I'd say leave it as-is. (Also, changing questions such that they invalidate existing answers is pretty frowned-upon on SO.)Jaggery
@RSinohara: FWIW, I've also corrected an error in the answer and added some detail as well as a way to test.Jaggery
Very interesting, putting the clearInterval inside the callback is the key to the proof. Very nice.Rabinowitz
Do you have any data on browsers that do not implement this standard though?Rabinowitz
@RSinohara: Not really. var timer = setInterval(...); busyWaitForTooLong(); clearInterval(timer); demonstrates it as well.Jaggery
@RSinohara: No. Current Chrome and Firefox, and IE11, all work as advertised (I checked them with the snippet above). :-) I don't have a copy of Edge handy right now.Jaggery

© 2022 - 2024 — McMap. All rights reserved.