在 JavaScript 中以预定义的不规则间隔调用函数

Call function at predefined irregular intervals in JavaScript

我必须 运行 在用户执行某些操作(如单击按钮)后的一些预定义的不规则间隔后编写一些代码。

间隔可以是 [1, 1.2, 2.05, 2.8, ...., 10.56][0.2, 1.5, 3.9, 4.67, 6.8, .., 12.0] 或其他。因此,应在初始按钮单击后 1 秒、1.2 秒、2.05 秒等后调用该函数。

我如何在 JavaScript 中做到这一点?

您在一个函数中使用 setTimeout,该函数被 调用 setTimeout:

// intervals in seconds
const intervals = [1, 1.2, 2.05, 2.8, 10.56];

(function runIrregularly(runThisCode) {
  if (intervals.length > 0) {
    // get (and remove) the first element from the array:
    const timeout = intervals.shift();

    // and schedule the next call to run in the future
    setTimeout(
      () => runIrregularly(runThisCode),
      timeout * 1000
    );
  }

  // then run our real function
  runThisCode();
})(doSomething);

function doSomething() {
  console.log(Date.now());
}

现在,当我们使用 shift() 从数组的开头获取元素时,您应该在那个时候去“嗯,所以它甚至不关心它是一个数组吗?”事实上:因为这段代码不会迭代任何东西,你甚至可以用一个生成函数来替换它,这个生成函数会根据需要提供值:

function getNextInterval() {
  // do whatever you like here
  return some number;
}

(function runIrregularly(runThisCode) {
  if (intervals.length > 0) {
    const timeout = getNextInterval();

    ...

(如果你愿意,你甚至可以使用 generator function 来获得幻想)

此外,我们当然不必“像我们声明的那样”调用函数,我们也可以单独声明和使用它:

function runIrregularly(runThisCode) {
  if (intervals.length > 0) {
    ...
  }
  runThisCode();
}

// and then at some later point in the code

runIrregularly(doSomething);

最后,如果你需要循环,而不是运行一次,我们可以结合shiftpush,并在开始时复制间隔列表:

function runIrregularly(runThisCode, intervals) {
  // get and remove the first element from the array
  const timeout = intervals.shift();

  // then push it back on as the last element.
  intervals.push(timeout);

  setTimeout(
    () => runIrregularly(runThisCode, intervals),
    timeout * 1000
  );
  
  runThisCode();
}

// and then later:
runIrregularly(doSomething, intervals.slice());

interval.slice() 是必要的,这样我们就可以保留原始数组的原始状态(否则用于其他函数将使它们不会在您的第一个间隔开始,而是“无论我们在循环中的哪个位置”基于然而许多电话是 运行ning)。

如何捕获和停止超时,我将作为练习留给 reader(web/SO 上有很多关于此的 questions/posts 可供查找)。

您也可以将 async/await 与 setTimeout 结合使用:

setTimeout(function() {

}, 1000);

将在 1 秒后执行函数。

您可以通过嵌套 setTimeout 调用(参见 Mike 的回答)或承诺 (async/await) 来实现您的目标:

function delayExecution(n) {
    return new Promise((resolve) => {
        setTimeout(resolve, n)
    })
}

async function runIrregularly(fn, delays) {
    for (const delay of delays) {
        // suspend execution by `delay` amounts of seconds
        await delayExecution(delay * 1000)

        fn()
    }
}

runIrregularly(() => {
    console.log(Date.now(), "Hello")
}, [1, 2, 3])