将clearInterval停止排队间隔执行

RSi*_*ara 2 javascript clearinterval

假设我有这些

myInterval=setInterval(funcA,50);

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

setTimeout(function(){clearInterval(myInterval);},10000}
Run Code Online (Sandbox Code Playgroud)

假设funcA总是花费超过50ms来简化它.当然,许多funcA运行会堆积起来并排队.clearInterval会删除那些排队的运行还是只是停止排队新运行

我确实做了一个小提琴来测试它,结果发现clearInterval会停止所有未来的执行,即使是已经排队的那些.我只需要确认这种行为是一致的(跨浏览器/平台).

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);
}
Run Code Online (Sandbox Code Playgroud)

--Update--

此问题中的排队执行假设不正确,请查看TJ Crowder的答案以获得解释.

T.J*_*der 5

当然,许多funcA运行会堆积起来并排队.

不,他们不会,因为重复计时器的工作方式.浏览器中的计时器行为(现在)由WHAT-WG"HTML5"规范指定.在回调完成后,将下一个任务排队,作为上一个任务的一部分完成,而不是与其分开; 这里详细介绍.因此,一次只会有一个未完成的任务(在它排队之后,在JavaScript引擎可以启动并处理它之前).

clearInterval删除那些排队的运行或只是停止排队新的?

不*,但它没有.计时器系统排队的任务的第一步是查看计时器是否仍在活动计时器列表中; 如果不是,在调用回调之前终止任务.所以就好像 clearInterval删除了任务(例如,你以前排队的回调没有运行),但不是因为clearInterval清除它(相反,这是因为检查了任务).

测试并证明行为很容易:只需安排一个计时器,然后忙等待的时间超过其间隔,然后清除它:

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");
}
Run Code Online (Sandbox Code Playgroud)

请注意,计时器仅触发一次,并且不会再次触发,即使在我们忙碌等待时,可能至少有一个触发它的任务已排队.


*("否" - 描述clearInterval并未说明有关读入待处理任务列表和删除按时间间隔排队但尚未获取的任务的情况.)