Javascript 如何使用clearTimeout停止嵌套的setTimeout?

Javascript 如何使用clearTimeout停止嵌套的setTimeout?,javascript,Javascript,我有一个函数everyXsecsForYsecs,它将接受三个参数:一个函数、以秒为单位的间隔时间和以秒为单位的总时间 everyXsecsForYsecs应每隔X*1000毫秒调用一次给定函数,但在Y*1000毫秒后停止调用该函数。除此之外,这里还有一个用于everyXsecsForYsecs的简单回调函数: function sayHowdy(){ console.log('Howdy'); } 然后我调用everyXsecsForYsecs,如下所示: everyXsecsForYs

我有一个函数
everyXsecsForYsecs
,它将接受三个参数:一个函数、以秒为单位的间隔时间和以秒为单位的总时间

everyXsecsForYsecs
应每隔
X*1000
毫秒调用一次给定函数,但在
Y*1000
毫秒后停止调用该函数。除此之外,这里还有一个用于
everyXsecsForYsecs
的简单回调函数:

function sayHowdy(){
  console.log('Howdy');
}
然后我调用
everyXsecsForYsecs
,如下所示:

everyXsecsForYsecs(sayHowdy, 1, 5);
因此,我期望在控制台中看到5个“Howdy”,然后函数停止。但实际情况是,函数永远打印“你好”。下面是我如何实现everyXsecsForYsecs的

function everyXsecsForYsecs(callback, X, Y) {
  x_mili = X * 1000;
  y_mili = Y * 1000;

let id = setTimeout(function run(){
    callback();
    id = setTimeout(run, x_mili);
  }, x_mili);
setTimeout(clearTimeout, y_mili, id);
}
我怀疑我如何将
clearTimeout
与嵌套的
setTimeout
一起使用, 我到底错过了什么?

到时候

 setTimeout(clearTimeout, y_mili, id);
运行时,
id
包含第一个外部
setTimeout
调用的计时器id。取消这项计划并没有真正的帮助。如果您将其替换为:

 setTimeout(() => clearTimeout(id),  y_mili);
当超时完成时,而不是开始时,当您评估
id
时,它将用
id
清除超时


我会这样写:

 function everyXsecsForYsecs(callback, X, Y) {
   let count = Math.floor(Y / X);
   function recurring() {
      callback();
      if((count -= 1) >= 0)
        setTimeout(recurring, X * 1000);
  }
  setTimeout(recurring, X * 1000);
 }
将在1000毫秒后调用sayHowdy,并将超时id存储在firstId中

如果调用此函数,则id引用的超时将被清除(无论超时是否已结束)

但问题是,为什么要清除超时,因为它不是间隔,所以您可能放错了框

看看这个片段,它不会重复几秒钟,而是用递归重复x次:

function fireAllXSecsYTimes(callback, fireAfterSeconds, counter) {
  if (counter === 0) {
    return;
  }
  setTimeout(() => {
    callback();
    counter--;
    fireAllXSecsYTimes(callback, fireAfterSeconds, counter);
  }, fireAfterSeconds * 1000)
}
你的要求:

function fireAllXSecsForYSecs(callback, fireAfterSeconds, remainingSeconds) {
  if (remainingSeconds <= 0) {
    return;
  }
  setTimeout(() => {
    callback();
    fireAllXSecsForYSecs(callback, fireAfterSeconds, remainingSeconds - fireAfterSeconds);
  }, fireAfterSeconds * 1000)
}
函数fireAllXSecsForYSecs(回调、fireAfterSeconds、remainingSeconds){
如果(剩余)秒{
回调();
fireAllXSecsForYSecs(回调、fireAfterSeconds、remainingSeconds-fireAfterSeconds);
},fireAfterSeconds*1000)
}
使用
fireAllXSecsForYSecs(()=>console.log('howdy'),2,5)调用

它将记录“howdy”3次,因为在第三次执行时,
remainingSeconds
仍然还有1次。如果要防止出现这种情况,只需返回If
remainingSeconds传递引用而不是值

函数sayHowdy(){
console.log('Howdy');
}
函数everyXsecsForYsecs(回调,X,Y){
x_mili=x*1000;
y_mili=y*1000;
let id=setTimeout(函数运行(){
回调();
id=设置超时(运行,x_mili);
},x_mili);
setTimeout(()=>clearTimeout(id),y_mili);
//这里您需要传递对id的引用,而不是值
//这是不断变化的
}

每秒钟(sayHowdy,1,5)谢谢你的回答,我犯的每一个基本错误。实际上,我这样做的唯一原因是能够使用嵌套超时并停止它。当然,您提供的代码片段也是一个合理的解决方案。谢谢。是的,我理解你的代码,你刚刚在y_mili之后清除了超时,但实际上你与x_mili的超时在这个时候已经运行了,所以不需要清除它。不客气。
function fireAllXSecsYTimes(callback, fireAfterSeconds, counter) {
  if (counter === 0) {
    return;
  }
  setTimeout(() => {
    callback();
    counter--;
    fireAllXSecsYTimes(callback, fireAfterSeconds, counter);
  }, fireAfterSeconds * 1000)
}
function fireAllXSecsForYSecs(callback, fireAfterSeconds, remainingSeconds) {
  if (remainingSeconds <= 0) {
    return;
  }
  setTimeout(() => {
    callback();
    fireAllXSecsForYSecs(callback, fireAfterSeconds, remainingSeconds - fireAfterSeconds);
  }, fireAfterSeconds * 1000)
}