简体   繁体   English

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

[英]How can I stop nested setTimeout with clearTimeout?

I have a function everyXsecsForYsecs that will accept three arguments: a function, an interval time in seconds, and a total time in seconds.我有一个 function everyXsecsForYsecs ,它将接受三个 arguments:一个 function,间隔时间(秒)和总时间(秒)。

everyXsecsForYsecs should invoke the given function every X * 1000 milliseconds, yet then stop invoking the function after Y * 1000 milliseconds. everyXsecsForYsecs应该每X * 1000毫秒调用一次给定的 function,然后在Y * 1000毫秒后停止调用 function。 Addition to this, here is a simple callback function for everyXsecsForYsecs :除此之外,这里是 everyXsecsForYsecs 的简单回调everyXsecsForYsecs

function sayHowdy(){
  console.log('Howdy');
}

Then I call everyXsecsForYsecs as such:然后我这样调用everyXsecsForYsecs

everyXsecsForYsecs(sayHowdy, 1, 5);

So what I expect is to see 5 'Howdy' in the console, then function to stop.所以我希望在控制台中看到 5 'Howdy',然后 function 停止。 But what happens is that, function prints 'Howdy' for ever.但发生的事情是,function 永远打印“你好”。 Here is how I implemented everyXsecsForYsecs ,这是我实现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);
}

I am suspicious about how I use clearTimeout with nested setTimeout , What I am missing exactly?我怀疑我如何将clearTimeout与嵌套的setTimeout一起使用,我到底错过了什么?

By the time到......的时候

 setTimeout(clearTimeout, y_mili, id);

runs, id contains the timer id of the first outer setTimeout call .运行时, id包含第一个外部setTimeout调用的计时器 id。 Cancelling that won't really help.取消那将无济于事。 If you'd replace it with:如果您将其替换为:

 setTimeout(() => clearTimeout(id),  y_mili);

it'll clear the timeout with the id at that time , as you evaluate id when the timeout is done , and not when it get's started .它会在那个时候id清除超时,因为你在超时完成时评估id ,而不是在它开始时


I'd write it as:我会把它写成:

 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);
 }
let firstId = setTimeout(sayHowdy, 1000)

will call sayHowdy after 1000ms and store the timeout id within firstId将在 1000 毫秒后调用 sayHowdy 并将超时 id 存储在 firstId 中

clearTimeout(firstId)

if this is called, the timeout referenced by the id will be cleared (no matter if it already is over or not)如果调用了这个,id引用的超时将被清除(不管它是否已经结束)

But the question actually is, why you would want to clear the timeout, it's no interval, so you probably are in the wrong box.但问题实际上是,为什么你要清除超时,它没有间隔,所以你可能在错误的框中。

have a look at this snippet, it does not repeat for seconds, but x times with recursion:看看这个片段,它不会重复几秒钟,而是递归 x 次:

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

what you asked for:你要求什么:

function fireAllXSecsForYSecs(callback, fireAfterSeconds, remainingSeconds) {
  if (remainingSeconds <= 0) {
    return;
  }
  setTimeout(() => {
    callback();
    fireAllXSecsForYSecs(callback, fireAfterSeconds, remainingSeconds - fireAfterSeconds);
  }, fireAfterSeconds * 1000)
}

called with fireAllXSecsForYSecs(() => console.log('howdy'), 2, 5) it will log 'howdy' 3 times, because on third execution, remainingSeconds still has 1 left.fireAllXSecsForYSecs(() => console.log('howdy'), 2, 5)调用它会记录 'howdy' 3 次,因为在第三次执行时, remainingSeconds还剩下 1 个。 If you want to prevent this, just return if remainingSeconds <= 0 || remainingSeconds < fireAfterSeconds如果你想防止这种情况,只要remainingSeconds <= 0 || remainingSeconds < fireAfterSeconds remainingSeconds <= 0 || remainingSeconds < fireAfterSeconds

Pass the reference not the value.传递引用而不是值。

 function sayHowdy() { console.log('Howdy'); } 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(id), y_mili); //here you need to pass the reference to the id not the value //which is constantly changing } everyXsecsForYsecs(sayHowdy, 1, 5);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM