首页 > 解决方案 > 如何停止 setTimeout 递归

问题描述

我创建了 setTimeout ,它有一个名为 run 的回调,在运行中我调用了 aconsole.log(i)来打印 I 的值,i++一旦达到 50,我想清除setTimeoutwith clearTimeout,我再次调用 setTimeout 并运行使其递归,但它不起作用。有人可以帮助我更好地理解这个概念吗?

let i = 1;

var abc = setTimeout(function run(){
   console.log(i);
if(i==50){
    abc1();
  }  
  i++;
  setTimeout(run,100);
},100);
function abc1(){
     clearTimeout(abc);
}

标签: javascriptrecursionsettimeout

解决方案


当您调用时,setTimeout您将获得返回的计时器的 ID。这正是您在这里所做的:

var abc = setTimeout(function run(){

但是,该 ID 仅在延迟函数执行之前有效。一旦这样做,它是无效的。当您打电话时,setTimeout(run,100);您将获得一个的计时器 ID。您需要再次捕获它,否则 ID 会丢失并且您无法阻止它。

还有最后一个考虑因素 - 即使您要正确捕获abc = setTimeout(run, 100);仍然不会停止计数器的 ID 调用,因为它会尝试停止现在正在运行的函数(它什么都不做),而不是取消执行下一个:

let i = 1;

var abc = setTimeout(function run() {
  console.log(i);
  if (i == 50) {
    abc1(); //this will clear the *current* timer 
  } 
  i++;
  abc = setTimeout(run, 100); //this will set the *new* ID 

}, 100);

function abc1() {
  clearTimeout(abc);
}

为了停止执行,您有两个选择。如果你想使用你最初的想法,你需要在调度之后取消未来的执行

let i = 1;

var abc = setTimeout(function run() {
  console.log(i);
  abc = setTimeout(run, 100); //this will set the *new* ID 
  if (i == 50) {
    abc1(); //this will clear the *new* timer now
  }
  i++;
}, 100);

function abc1() {
  clearTimeout(abc);
}

或者,您可以完全不使用计时器句柄来执行此操作,而只需使用if条件来确定您是否要安排另一个执行:

let i = 1;

setTimeout(function run() {
  console.log(i);
  if (i != 50) { //until 50 is reached
    abc = setTimeout(run, 100); //schedule a new execution
  }
  i++;
}, 100);


推荐阅读