探索 JavaScript 定时器

setTimeout()

在编写 JavaScript 代码时,您可能希望延迟执行某个函数。

这就是 setTimeout 的作用。您指定一个稍后执行的回调函数,以及一个值,表示您希望它延迟多长时间运行,以毫秒为单位。

setTimeout(() => {
  // runs after 2 seconds
}, 2000);

setTimeout(() => {
  // runs after 50 milliseconds
}, 50);

此语法定义了一个新函数。您可以在其中调用您想要的任何其他函数,或者您可以传递一个现有的函数名称和一组参数

const myFunction = (firstParam, secondParam) => {
  // do something
};

// runs after 2 seconds
setTimeout(myFunction, 2000, firstParam, secondParam);

setTimeout 返回计时器 ID。这通常不使用,但您可以存储此 ID,并在您想要删除此计划的函数执行时清除它

const id = setTimeout(() => {
  // should run after 2 seconds
}, 2000);

// I changed my mind
clearTimeout(id);

零延迟

如果您将超时延迟指定为 0,则回调函数将在当前函数执行后尽快执行

setTimeout(() => {
  console.log('after ');
}, 0);

console.log(' before ');

此代码将打印

before
after

这对于避免在密集任务上阻塞 CPU 并让其他函数在执行繁重的计算时执行非常有用,方法是在调度程序中排队函数。

一些浏览器(IE 和 Edge)实现了 setImmediate() 方法,它执行完全相同的功能,但它不是标准的,并且 在其他浏览器上不可用。但它是 Node.js 中的标准函数。

setInterval()

setInterval 是一个类似于 setTimeout 的函数,不同之处在于:它不会只运行回调函数一次,而是会根据您指定的特定时间间隔(以毫秒为单位)永远运行它

setInterval(() => {
  // runs every 2 seconds
}, 2000);

上面的函数每 2 秒运行一次,除非您告诉它停止,使用 clearInterval,将 setInterval 返回的间隔 ID 传递给它

const id = setInterval(() => {
  // runs every 2 seconds
}, 2000);

clearInterval(id);

通常在 setInterval 回调函数内部调用 clearInterval,以让它自动决定是否应该继续运行或停止。例如,这段代码会运行某些操作,除非 App.somethingIWait 的值为 arrived

const interval = setInterval(() => {
  if (App.somethingIWait === 'arrived') {
    clearInterval(interval);
  }
  // otherwise do things
}, 100);

递归 setTimeout

setInterval 每隔 n 毫秒启动一个函数,而不考虑函数何时完成执行。

如果一个函数始终花费相同的时间,那么一切正常。

setInterval working fine

也许函数的执行时间不同,例如取决于网络状况。

setInterval varying duration

也许一次长时间的执行会与下一次执行重叠。

setInterval overlapping

为了避免这种情况,可以在回调函数完成时安排一个递归的 setTimeout 被调用。

const myFunction = () => {
  // do something

  setTimeout(myFunction, 1000);
};

setTimeout(myFunction, 1000);

以实现这种情况

Recursive setTimeout

setTimeoutsetInterval 在 Node.js 中可用,通过 Timers 模块

Node.js 还提供 setImmediate(),它等效于使用 setTimeout(() => {}, 0),主要用于与 Node.js 事件循环配合使用。