javascript 是否有办法交替setInterval持续时间?

ejk8hzay  于 2022-10-30  发布在  Java
关注(0)|答案(4)|浏览(133)

我希望能够以两种不同的长度交替调用setInterval(或类似的东西)。
例如,在5秒后运行函数,然后1秒,再运行5秒,依此类推。
这可能吗?我尝试了一个函数来替换值,但它似乎不起作用。

let num = 5000

function alternateNum() {
  if (num === 5000) { num = 1000 }
  else { num = 5000 }
}

setInterval(() => {
  // ...

  alternateNum()
}, num);
smdnsysy

smdnsysy1#

setInterval()的问题是只考虑了一次时间,你可以用setTimeout()来代替递归:

function doAction(flipFlop) {
  setTimeout(() => {
    console.log(flipFlop ? 'flip' : 'flop');
    doAction(!flipFlop);
    // do some other action...
  }, flipFlop ? 1000 : 3000);
}

doAction(true);

但是如果你有一个长时间运行的过程,要小心,这种递归会越来越深。

gojuced7

gojuced72#

我觉得这个方法最简单:

setInterval(() => {
    console.log("first");
    setTimeout(() => console.log("second"), 750);
}, 2000);

这将创建一个在1250和750毫秒之间交替的间隔。

djmepvbi

djmepvbi3#

代码的问题

let num = 5000

function alternateNum() {
  if (num === 5000) { num = 1000 }
  else { num === 5000 }
}

setInterval(() => {
  // ...
  alternateNum()
}, num);

最后几行(setInterval)调用只被调用一次,初始值为num,因此,对num的任何未来更改都不会反映在setTimeout调用中。
如何修复它
您应该在包含代码的函数中使用setTimeout,并递归调用函数:

const doStuff = (time = 1000) => {
    // Your code here

    // generate the next time to wait
    const nextTime = time === 5000 ? 1000 : 5000;
    // call the function again after waiting `time` milliseconds
    setInterval(() => doStuff(nextTime), time);
}

然后调用doStuff来启动它。如果你想立即启动它,下一个在1秒后发生,你可以这样做:

doStuff();

或者,如果您想在5秒后调用它,而下一个调用在该时间的1秒后发生:

setTimeout(doStuff, 5000);

与您的代码相比,这里的不同之处在于,表示时间的变量在更改时会被反复使用,而不是在初始代码执行时只使用一次。

lqfhib0f

lqfhib0f4#

JS计时器有一个非常复杂的历史。
使用递归setTimeout调用是一个简单而优雅的解决方案(只要您的运行时实现tail call optimization)。
与递归问题不同的是定时器漂移问题,如果你想了解这个问题的介绍,可以在YouTube视频JavaScript counters the hard way - HTTP 203中找到。
在许多JS引擎(例如V8)中,setInterval将为您处理漂移校正,因此使用它实际上比递归调用setTimeout有一个优势。(检查下面代码片段中控制台消息中的毫秒时间戳来验证这一点。)
为了确定setInterval所需的恒定间隔参数,需要找到延迟持续时间的greatest common factor。一旦得到这个值,就可以将其用作基本间隔延迟,并跟踪间隔状态,以确定是否应该切换到下一个间隔延迟,运行其他代码等。下面是一个最小的示例:

const durations = [1000, 5000];

// If you can't determine this in advance and use a constant value,
// then you can calculate it at runtime using a function:
const gcf = 1000; // or const gcf = findGreatestCommonFactor(durations);

let durationIndex = 0;
let elapsed = 0;

function update () {
  elapsed += gcf;
  const ready = elapsed === durations[durationIndex];
  if (ready) {
    elapsed = 0;
    durationIndex = (durationIndex + 1) % durations.length;
  }
  return ready;
}

setInterval(() => {
  const ready = update();
  if (!ready) return;

  // Do your interval task, for example:
  console.log('tick');
}, gcf);

相关问题