如何停止 setTimeout 递归

how to stop the setTimeout recursion

我创建了 setTimeout,它有一个名为 运行 的回调,在 运行 中我调用了一个 console.log(i) 来打印 I 的值 i++ 和一旦达到 50,我想用 clearTimeout 清除 setTimeout,我用 运行 再次调用 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);
}

运行() 中的 setTimeout() 未分配给任何变量,因此无法以任何方式清除。

我想你想要的是覆盖 abc 所以你必须替换:

setTimeout(run,100);

来自

abc = setTimeout(run,100);

由于 var abc 只设置一次,在第一次超时时,您只清除第一个超时,这很可能已经完成。

SetTimeout returns 一个数值,这是一个 ID 来引用该任务。调用clearTimeout时必须通知ID要清除的超时,现在通知ID是第一次超时,已经结束了,不能清除。

如果您想清除上次超时,也许您希望始终使用每次超时的 ID 更新 abc,如下所示:

 abc = setTimeout(run,100);

这是一种执行定时循环的奇怪方式,但你只需要清除(实际上在这种情况下不是,但我还是喜欢这样做,因为一旦你不使用它们,释放资源是一个很好的做法不再)创建新超时之前的超时(通过跟踪 abc 句柄完成)和 return 在给定条件下的 clear 之后:

let i = 1;

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

function abc1(){
  clearTimeout(abc);
}

调用abc1函数后需要添加return。您清除了超时,但代码仍然 运行ning 并再次调用 setTimeout(运行,100)。

        let i = 1;

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

问题出在你的操作顺序上。

if(i==50){
    abc1();
  } 

如果 i 达到 50,将调用函数 abc1() - 清除间隔。

i++;
setTimeout(run,100);

您在这里重新开始间隔。 您需要将其包装在 else 块中。

let i = 1;

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

function abc1() {
  clearTimeout(abc);
}

let i = 1;

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

},100);

只有当计时器未运行超时时,您才应该运行超时。

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

var abc = setTimeout(function run(){

但是,该 ID 仅在延迟函数执行之前有效。一旦这样做,它是无效的。当您调用 setTimeout(run,100); 时,您将获得计时器的 new ID。需要重新抓取,否则ID会丢失,无法阻止。

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

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);
}

要停止执行,您有两种选择。如果你想使用你最初的想法,你需要取消以后的执行after is scheduled

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);